github.com/weaviate/weaviate@v1.24.6/test/acceptance/replication/graphql_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 graphqlSearch(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 paragraphClass.Vectorizer = "text2vec-contextionary" 47 articleClass := articles.ArticlesClass() 48 49 t.Run("create schema", func(t *testing.T) { 50 paragraphClass.ReplicationConfig = &models.ReplicationConfig{ 51 Factor: 2, 52 } 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 t.Run("get consistent search results with ONE (1/2 nodes up)", func(t *testing.T) { 88 resp := gqlGet(t, compose.GetWeaviate().URI(), paragraphClass.Class, replica.One) 89 checkResultsConsistency(t, resp, true) 90 }) 91 92 t.Run("restart node 2", func(t *testing.T) { 93 err = compose.Start(ctx, compose.GetWeaviateNode2().Name()) 94 require.Nil(t, err) 95 }) 96 97 t.Run("get consistent search results with ALL (2/2 nodes up)", func(t *testing.T) { 98 resp := gqlGet(t, compose.GetWeaviate().URI(), paragraphClass.Class, replica.All) 99 checkResultsConsistency(t, resp, true) 100 }) 101 102 t.Run("get consistent search results with QUORUM (2/2 nodes up)", func(t *testing.T) { 103 resp := gqlGet(t, compose.GetWeaviate().URI(), paragraphClass.Class, replica.Quorum) 104 checkResultsConsistency(t, resp, true) 105 }) 106 107 t.Run("get consistent search results with ONE (2/2 nodes up)", func(t *testing.T) { 108 resp := gqlGet(t, compose.GetWeaviate().URI(), paragraphClass.Class, replica.One) 109 checkResultsConsistency(t, resp, true) 110 }) 111 112 t.Run("get consistent search results with ONE (2/2 nodes up)", func(t *testing.T) { 113 resp := gqlGet(t, compose.GetWeaviate().URI(), paragraphClass.Class, replica.One) 114 require.GreaterOrEqual(t, len(resp), 1) 115 vec := resp[0].(map[string]interface{})["_additional"].(map[string]interface{})["vector"].([]interface{}) 116 resp = gqlGetNearVec(t, compose.GetWeaviate().URI(), paragraphClass.Class, vec, replica.Quorum) 117 checkResultsConsistency(t, resp, true) 118 }) 119 } 120 121 func checkResultsConsistency(t *testing.T, results []interface{}, expectConsistent bool) { 122 for _, res := range results { 123 addl := res.(map[string]interface{})["_additional"].(map[string]interface{}) 124 if expectConsistent { 125 assert.True(t, addl["isConsistent"].(bool)) 126 } else { 127 assert.False(t, addl["isConsistent"].(bool)) 128 } 129 } 130 }