Open nkev opened 2 weeks ago
Sorry for the late reply! Here is a modified version that works:
type User struct {
ID uuid.UUID
Name string
Score int64
Emails []string //List test
Address struct { //Map test
Number int64
Street string
Postcode string
}
}
func (u *User) ToCRDT(doc *Automerge) *Automerge {
tx := doc.StartTransaction()
tx.Put(ExRootOpId, "name", u.Name)
tx.Put(ExRootOpId, "score", u.Score)
//add email LIST
emails, _ := tx.PutObject(ExRootOpId, "emails", opset.LIST)
for _, e := range u.Emails {
tx.Insert(emails, 0, e)
}
//add address MAP
address, _ := tx.PutObject(ExRootOpId, "address", opset.MAP)
tx.Put(address, "number", u.Address.Number)
tx.Put(address, "street", u.Address.Street)
tx.Put(address, "postcode", u.Address.Postcode)
doc.CommitTransaction()
return doc
}
func CreateTestUsers() (localUser, remoteUser User) {
userID, _ := uuid.NewRandom() //we are merging the same user record between remote and local versions
localUser = User{ //user record from local server
ID: userID,
Name: "Jon",
Score: 100,
Emails: []string{"lu1@test.com", "lu2@test.com"},
Address: struct {
Number int64
Street string
Postcode string
}{
Number: 11,
Street: "Local St",
Postcode: "Local Postcode",
},
}
remoteUser = User{ //same user record with mutations from a remote server
ID: userID,
Name: "Jonathan",
Score: 120,
Emails: []string{"lu1@test.com", "ru1@test.com", "ru2@test.com"},
Address: struct {
Number int64
Street string
Postcode string
}{
Number: 111,
Street: "Remote St",
Postcode: "Remote Postcode",
},
}
return
}
func TestStructMerge1(t *testing.T) {
doc1 := NewAutomerge(uuid.New())
doc2 := doc1.Fork()
localUser, remoteUser := CreateTestUsers()
cLocalUser := localUser.ToCRDT(doc1)
cRemoteUser := remoteUser.ToCRDT(doc2)
// merge localUser and remoteUser
cLocalUser.Merge(cRemoteUser)
cRemoteUser.Merge(cLocalUser)
// ensure localUser and remoteUser are the same
txLoc := cLocalUser.StartTransaction()
txRem := cRemoteUser.StartTransaction()
nameLoc, _ := txLoc.Get(ExRootOpId, "name")
nameRem, _ := txRem.Get(ExRootOpId, "name")
assert.Equal(t, nameLoc, nameRem)
scoreLoc, _ := txLoc.Get(ExRootOpId, "score")
scoreRem, _ := txRem.Get(ExRootOpId, "score")
assert.Equal(t, scoreLoc, scoreRem)
emailsLoc, _ := txLoc.Get(ExRootOpId, "emails")
emailsLocId := emailsLoc.(ExOpId)
emailsRem, _ := txRem.Get(ExRootOpId, "emails")
emailsRemId := emailsRem.(ExOpId)
for i := 0; i < 2; i++ {
emLoc, _ := txLoc.Get(emailsLocId, i)
emRem, _ := txRem.Get(emailsRemId, i)
assert.Equal(t, emLoc, emRem)
}
addressMapLoc, _ := txLoc.Get(ExRootOpId, "address")
addressMapLocId := addressMapLoc.(ExOpId)
num, _ := txLoc.Get(addressMapLocId, "number")
addressMapRem, _ := txRem.Get(ExRootOpId, "address")
addressMapRemId := addressMapRem.(ExOpId)
numRem, _ := txRem.Get(addressMapRemId, "number")
assert.Equal(t, num, numRem)
// cLocalUser.CommitTransaction()
// cRemoteUser.CommitTransaction()
}
However, I noticed that you didn't use Move
operation in your example. If you don't need a move operation at all, I would suggest using the real Automerge library instead: https://github.com/automerge/automerge. AutomergeWIthMove is an experimental codebase that tries to enhance the real Automerge library with move operations.
Thanks for sharing this!
I wanted to try a real-world example of this CRDT. For example, merging a remote user record with a local one.
I tried a new test file
automerge_struct_test.go
below but the two user structs seem to just swap their data. Could you please point me in the right direction?