SemanticSearchPOC / test /acceptance /objects /rapid_updates_add_reference_test.go
KevinStephenson
Adding in weaviate code
b110593
raw
history blame
4.99 kB
// _ _
// __ _____ __ ___ ___ __ _| |_ ___
// \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \
// \ V V / __/ (_| |\ V /| | (_| | || __/
// \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___|
//
// Copyright © 2016 - 2024 Weaviate B.V. All rights reserved.
//
// CONTACT: [email protected]
//
package test
import (
"fmt"
"strings"
"testing"
"time"
"github.com/go-openapi/strfmt"
"github.com/stretchr/testify/assert"
"github.com/weaviate/weaviate/client/objects"
clschema "github.com/weaviate/weaviate/client/schema"
"github.com/weaviate/weaviate/entities/models"
"github.com/weaviate/weaviate/entities/schema"
"github.com/weaviate/weaviate/test/helper"
)
// This aims to prevent a regression on
// https://github.com/weaviate/weaviate/issues/1016
// The issue was that rapid POST .../references/... request in succession would
// overwrite each other due to the eventual consistency nature of the used
// backend (esvector). This bug is considered fix if n items can be rapidly
// added and a subsequent GET request of the source resource contains all
// previously added references.
func Test_RapidlyAddingReferences(t *testing.T) {
sourceClass := "SequenceReferenceTestSource"
targetClass := "SequenceReferenceTestTarget"
sourceID := strfmt.UUID("96ce03ca-58ed-48e1-a0f1-51f63fa9aa12")
targetIDs := []strfmt.UUID{
"ce1a4756-b7ce-44fa-b079-45a7ec400882",
"e1edb4ff-570c-4f0b-a1a1-18af118369aa",
"25d22c70-3df0-4e5c-b8c1-a88d4d2771ef",
"6f2a0708-3e8e-4a68-9763-26c465d8bf83",
"c4dfae47-ebcf-4808-9122-1c67898ec140",
"754bd925-1900-4f93-9f5d-27631eb618bb",
"babba820-e3f5-4e8d-a354-76f2cb13fdba",
"270942da-1999-40cd-a580-a91aa144b6c0",
"a7a06618-6d50-4654-be75-2c9f639a6368",
"47ba1d2b-6b8c-4b3b-92a8-46574a069ae8",
}
t.Run("adding the required schema", func(t *testing.T) {
t.Run("target class", func(t *testing.T) {
params := clschema.NewSchemaObjectsCreateParams().WithObjectClass(
&models.Class{
Class: targetClass,
Properties: []*models.Property{
{
DataType: schema.DataTypeText.PropString(),
Tokenization: models.PropertyTokenizationWhitespace,
Name: "name",
},
},
},
)
resp, err := helper.Client(t).Schema.SchemaObjectsCreate(params, nil)
helper.AssertRequestOk(t, resp, err, nil)
})
t.Run("source class", func(t *testing.T) {
params := clschema.NewSchemaObjectsCreateParams().WithObjectClass(
&models.Class{
Class: sourceClass,
Properties: []*models.Property{
{
DataType: []string{targetClass},
Name: "toTarget",
},
{
DataType: schema.DataTypeText.PropString(),
Tokenization: models.PropertyTokenizationWhitespace,
Name: "name",
},
},
},
)
resp, err := helper.Client(t).Schema.SchemaObjectsCreate(params, nil)
helper.AssertRequestOk(t, resp, err, nil)
})
})
t.Run("adding all objects (without referencing)", func(t *testing.T) {
t.Run("source object", func(t *testing.T) {
assertCreateObjectWithID(t, sourceClass, "", sourceID, map[string]interface{}{
"name": "Source Object",
})
})
t.Run("target objects", func(t *testing.T) {
for i, id := range targetIDs {
assertCreateObjectWithID(t, targetClass, "", id, map[string]interface{}{
"name": fmt.Sprintf("target object %d", i),
})
}
})
})
t.Run("waiting for the last added object to be present", func(t *testing.T) {
assertGetObjectEventually(t, targetIDs[len(targetIDs)-1])
})
t.Run("placing all references in succession", func(t *testing.T) {
for _, id := range targetIDs {
params := objects.NewObjectsReferencesCreateParams().
WithID(sourceID).
WithPropertyName("toTarget").
WithBody(
&models.SingleRef{
Beacon: strfmt.URI(fmt.Sprintf("weaviate://localhost/%s", id)),
},
)
res, err := helper.Client(t).Objects.ObjectsReferencesCreate(params, nil)
helper.AssertRequestOk(t, res, err, nil)
}
})
// wait for index refresh
time.Sleep(2 * time.Second) // TODO: improve through polling
t.Run("checking which refs were set", func(t *testing.T) {
source := assertGetObject(t, sourceID)
var foundIDs []strfmt.UUID
// extract IDs
for _, ref := range source.Properties.(map[string]interface{})["toTarget"].([]interface{}) {
beacon := ref.(map[string]interface{})["beacon"].(string)
chunks := strings.Split(beacon, "/")
foundIDs = append(foundIDs, strfmt.UUID(chunks[len(chunks)-1]))
}
assert.ElementsMatch(t, targetIDs, foundIDs)
})
// cleanup
helper.Client(t).Schema.SchemaObjectsDelete(
clschema.NewSchemaObjectsDeleteParams().WithClassName(sourceClass), nil)
helper.Client(t).Schema.SchemaObjectsDelete(
clschema.NewSchemaObjectsDeleteParams().WithClassName(targetClass), nil)
}