github.com/weaviate/weaviate@v1.24.6/test/acceptance/replication/read_repair_test.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package replication 13 14 import ( 15 "context" 16 "fmt" 17 "testing" 18 "time" 19 20 "github.com/stretchr/testify/assert" 21 "github.com/stretchr/testify/require" 22 "github.com/weaviate/weaviate/entities/models" 23 "github.com/weaviate/weaviate/test/docker" 24 "github.com/weaviate/weaviate/test/helper" 25 "github.com/weaviate/weaviate/test/helper/sample-schema/articles" 26 "github.com/weaviate/weaviate/usecases/replica" 27 ) 28 29 func readRepair(t *testing.T) { 30 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) 31 defer cancel() 32 33 compose, err := docker.New(). 34 WithWeaviateCluster(). 35 WithText2VecContextionary(). 36 Start(ctx) 37 require.Nil(t, err) 38 defer func() { 39 if err := compose.Terminate(ctx); err != nil { 40 t.Fatalf("failed to terminate test containers: %s", err.Error()) 41 } 42 }() 43 44 helper.SetupClient(compose.GetWeaviate().URI()) 45 paragraphClass := articles.ParagraphsClass() 46 articleClass := articles.ArticlesClass() 47 48 t.Run("create schema", func(t *testing.T) { 49 paragraphClass.ReplicationConfig = &models.ReplicationConfig{ 50 Factor: 2, 51 } 52 paragraphClass.Vectorizer = "text2vec-contextionary" 53 helper.CreateClass(t, paragraphClass) 54 articleClass.ReplicationConfig = &models.ReplicationConfig{ 55 Factor: 2, 56 } 57 helper.CreateClass(t, articleClass) 58 }) 59 60 t.Run("insert paragraphs", func(t *testing.T) { 61 batch := make([]*models.Object, len(paragraphIDs)) 62 for i, id := range paragraphIDs { 63 batch[i] = articles.NewParagraph(). 64 WithID(id). 65 WithContents(fmt.Sprintf("paragraph#%d", i)). 66 Object() 67 } 68 createObjects(t, compose.GetWeaviate().URI(), batch) 69 }) 70 71 t.Run("insert articles", func(t *testing.T) { 72 batch := make([]*models.Object, len(articleIDs)) 73 for i, id := range articleIDs { 74 batch[i] = articles.NewArticle(). 75 WithID(id). 76 WithTitle(fmt.Sprintf("Article#%d", i)). 77 Object() 78 } 79 createObjects(t, compose.GetWeaviateNode2().URI(), batch) 80 }) 81 82 t.Run("stop node 2", func(t *testing.T) { 83 stopNode(ctx, t, compose, compose.GetWeaviateNode2().Name()) 84 time.Sleep(10 * time.Second) 85 }) 86 87 repairObj := models.Object{ 88 ID: "e5390693-5a22-44b8-997d-2a213aaf5884", 89 Class: "Paragraph", 90 Properties: map[string]interface{}{ 91 "contents": "a new paragraph", 92 }, 93 } 94 95 t.Run("add new object to node one", func(t *testing.T) { 96 createObjectCL(t, compose.GetWeaviate().URI(), &repairObj, replica.One) 97 }) 98 99 t.Run("restart node 2", func(t *testing.T) { 100 err = compose.Start(ctx, compose.GetWeaviateNode2().Name()) 101 require.Nil(t, err) 102 }) 103 104 t.Run("run fetch to trigger read repair", func(t *testing.T) { 105 _, err := getObject(t, compose.GetWeaviate().URI(), repairObj.Class, repairObj.ID, true) 106 require.Nil(t, err) 107 }) 108 109 t.Run("assert new object read repair was made", func(t *testing.T) { 110 stopNode(ctx, t, compose, compose.GetWeaviate().Name()) 111 time.Sleep(10 * time.Second) 112 113 resp, err := getObjectCL(t, compose.GetWeaviateNode2().URI(), 114 repairObj.Class, repairObj.ID, replica.One) 115 require.Nil(t, err) 116 assert.Equal(t, repairObj.ID, resp.ID) 117 assert.Equal(t, repairObj.Class, resp.Class) 118 assert.EqualValues(t, repairObj.Properties, resp.Properties) 119 assert.EqualValues(t, repairObj.Vector, resp.Vector) 120 }) 121 122 replaceObj := repairObj 123 replaceObj.Properties = map[string]interface{}{ 124 "contents": "this paragraph was replaced", 125 } 126 127 t.Run("replace object", func(t *testing.T) { 128 updateObjectCL(t, compose.GetWeaviateNode2().URI(), &replaceObj, replica.One) 129 }) 130 131 t.Run("restart node 1", func(t *testing.T) { 132 restartNode1(ctx, t, compose) 133 }) 134 135 t.Run("run exists to trigger read repair", func(t *testing.T) { 136 exists, err := objectExistsCL(t, compose.GetWeaviateNode2().URI(), 137 replaceObj.Class, replaceObj.ID, replica.All) 138 require.Nil(t, err) 139 require.True(t, exists) 140 }) 141 142 t.Run("assert updated object read repair was made", func(t *testing.T) { 143 stopNode(ctx, t, compose, compose.GetWeaviateNode2().Name()) 144 time.Sleep(10 * time.Second) 145 146 exists, err := objectExistsCL(t, compose.GetWeaviate().URI(), 147 replaceObj.Class, replaceObj.ID, replica.One) 148 require.Nil(t, err) 149 require.True(t, exists) 150 151 resp, err := getObjectCL(t, compose.GetWeaviate().URI(), 152 repairObj.Class, repairObj.ID, replica.One) 153 require.Nil(t, err) 154 assert.Equal(t, replaceObj.ID, resp.ID) 155 assert.Equal(t, replaceObj.Class, resp.Class) 156 assert.EqualValues(t, replaceObj.Properties, resp.Properties) 157 assert.EqualValues(t, replaceObj.Vector, resp.Vector) 158 }) 159 }