Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move Presence to Document #582

Merged
merged 7 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion admin/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ func (c *Client) ListChangeSummaries(
}
var summaries []*types.ChangeSummary
for _, c := range changes {
if err := newDoc.ApplyChanges(c); err != nil {
if _, err := newDoc.ApplyChanges(c); err != nil {
return nil, err
}

Expand Down
44 changes: 16 additions & 28 deletions api/converter/converter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ import (
"github.com/stretchr/testify/assert"

"github.com/yorkie-team/yorkie/api/converter"
"github.com/yorkie-team/yorkie/api/types"
api "github.com/yorkie-team/yorkie/api/yorkie/v1"
"github.com/yorkie-team/yorkie/pkg/document"
"github.com/yorkie-team/yorkie/pkg/document/crdt"
"github.com/yorkie-team/yorkie/pkg/document/innerpresence"
"github.com/yorkie-team/yorkie/pkg/document/json"
"github.com/yorkie-team/yorkie/pkg/document/presence"
"github.com/yorkie-team/yorkie/pkg/document/time"
"github.com/yorkie-team/yorkie/test/helper"
)
Expand All @@ -41,14 +42,14 @@ func TestConverter(t *testing.T) {

doc := document.New("d1")

err = doc.Update(func(root *json.Object) error {
err = doc.Update(func(root *json.Object, p *presence.Presence) error {
root.SetNewText("k1").Edit(0, 0, "A")
return nil
})
assert.NoError(t, err)
assert.Equal(t, `{"k1":[{"val":"A"}]}`, doc.Marshal())

err = doc.Update(func(root *json.Object) error {
err = doc.Update(func(root *json.Object, p *presence.Presence) error {
root.SetNewText("k1").Edit(0, 0, "B")
return nil
})
Expand All @@ -63,10 +64,10 @@ func TestConverter(t *testing.T) {
assert.Equal(t, `{"k1":[{"val":"B"}]}`, obj.Marshal())
})

t.Run("snapshot test", func(t *testing.T) {
t.Run("root snapshot test", func(t *testing.T) {
doc := document.New("d1")

err := doc.Update(func(root *json.Object) error {
err := doc.Update(func(root *json.Object, p *presence.Presence) error {
// an object and primitive types
root.SetNewObject("k1").
SetNull("k1.0").
Expand Down Expand Up @@ -138,7 +139,7 @@ func TestConverter(t *testing.T) {
t.Run("change pack test", func(t *testing.T) {
d1 := document.New("d1")

err := d1.Update(func(root *json.Object) error {
err := d1.Update(func(root *json.Object, p *presence.Presence) error {
// an object and primitive types
root.SetNewObject("k1").
SetBool("k1.1", true).
Expand Down Expand Up @@ -209,28 +210,6 @@ func TestConverter(t *testing.T) {
assert.ErrorIs(t, err, converter.ErrCheckpointRequired)
})

t.Run("client test", func(t *testing.T) {
cli := types.Client{
ID: time.InitialActorID,
PresenceInfo: types.PresenceInfo{
Presence: types.Presence{"Name": "ClientName"},
},
}

pbCli := converter.ToClient(cli)
decodedCli, err := converter.FromClient(pbCli)
assert.NoError(t, err)
assert.Equal(t, cli.ID.Bytes(), decodedCli.ID.Bytes())
assert.Equal(t, cli.PresenceInfo, decodedCli.PresenceInfo)

pbClients := converter.ToClients([]types.Client{cli})

decodedCli, err = converter.FromClient(pbClients[0])
assert.NoError(t, err)
assert.Equal(t, cli.ID.Bytes(), decodedCli.ID.Bytes())
assert.Equal(t, cli.PresenceInfo, decodedCli.PresenceInfo)
})

t.Run("tree converting test", func(t *testing.T) {
root := helper.BuildTreeNode(&json.TreeNode{
Type: "r",
Expand Down Expand Up @@ -264,4 +243,13 @@ func TestConverter(t *testing.T) {

assert.Equal(t, tree.ToXML(), clone.ToXML())
})

t.Run("empty presence converting test", func(t *testing.T) {
change, err := innerpresence.NewChangeFromJSON(`{"ChangeType":"put","Presence":{}}`)
assert.NoError(t, err)

pbChange := converter.ToPresenceChange(change)
clone := converter.FromPresenceChange(pbChange)
assert.Equal(t, change, clone)
})
}
21 changes: 21 additions & 0 deletions api/converter/from_bytes.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,30 @@ import (

api "github.com/yorkie-team/yorkie/api/yorkie/v1"
"github.com/yorkie-team/yorkie/pkg/document/crdt"
"github.com/yorkie-team/yorkie/pkg/document/innerpresence"
"github.com/yorkie-team/yorkie/pkg/document/time"
)

// BytesToSnapshot creates a Snapshot from the given byte array.
func BytesToSnapshot(snapshot []byte) (*crdt.Object, *innerpresence.Map, error) {
if snapshot == nil {
return crdt.NewObject(crdt.NewElementRHT(), time.InitialTicket), innerpresence.NewMap(), nil
}

pbSnapshot := &api.Snapshot{}
if err := proto.Unmarshal(snapshot, pbSnapshot); err != nil {
return nil, nil, fmt.Errorf("unmarshal snapshot: %w", err)
}

obj, err := fromJSONElement(pbSnapshot.GetRoot())
if err != nil {
return nil, nil, err
}

presences := fromPresences(pbSnapshot.GetPresences())
return obj.(*crdt.Object), presences, nil
}

// BytesToObject creates an Object from the given byte array.
func BytesToObject(snapshot []byte) (*crdt.Object, error) {
if snapshot == nil {
Expand Down
98 changes: 52 additions & 46 deletions api/converter/from_pb.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
api "github.com/yorkie-team/yorkie/api/yorkie/v1"
"github.com/yorkie-team/yorkie/pkg/document/change"
"github.com/yorkie-team/yorkie/pkg/document/crdt"
"github.com/yorkie-team/yorkie/pkg/document/innerpresence"
"github.com/yorkie-team/yorkie/pkg/document/key"
"github.com/yorkie-team/yorkie/pkg/document/operations"
"github.com/yorkie-team/yorkie/pkg/document/time"
Expand Down Expand Up @@ -119,27 +120,6 @@ func FromDocumentSummary(pbSummary *api.DocumentSummary) (*types.DocumentSummary
}, nil
}

// FromClient converts the given Protobuf formats to model format.
func FromClient(pbClient *api.Client) (*types.Client, error) {
id, err := time.ActorIDFromBytes(pbClient.Id)
if err != nil {
return nil, err
}

return &types.Client{
ID: id,
PresenceInfo: FromPresenceInfo(pbClient.Presence),
}, nil
}

// FromPresenceInfo converts the given Protobuf formats to model format.
func FromPresenceInfo(pbPresence *api.Presence) types.PresenceInfo {
return types.PresenceInfo{
Clock: pbPresence.Clock,
Presence: pbPresence.Data,
}
}

// FromChangePack converts the given Protobuf formats to model format.
func FromChangePack(pbPack *api.ChangePack) (*change.Pack, error) {
if pbPack == nil {
Expand Down Expand Up @@ -192,6 +172,7 @@ func FromChanges(pbChanges []*api.Change) ([]*change.Change, error) {
changeID,
pbChange.Message,
ops,
FromPresenceChange(pbChange.PresenceChange),
))
}

Expand Down Expand Up @@ -240,15 +221,13 @@ func FromEventType(pbDocEventType api.DocEventType) (types.DocEventType, error)
return types.DocumentsWatchedEvent, nil
case api.DocEventType_DOC_EVENT_TYPE_DOCUMENTS_UNWATCHED:
return types.DocumentsUnwatchedEvent, nil
case api.DocEventType_DOC_EVENT_TYPE_PRESENCE_CHANGED:
return types.PresenceChangedEvent, nil
}
return "", fmt.Errorf("%v: %w", pbDocEventType, ErrUnsupportedEventType)
}

// FromDocEvent converts the given Protobuf formats to model format.
func FromDocEvent(docEvent *api.DocEvent) (*sync.DocEvent, error) {
client, err := FromClient(docEvent.Publisher)
client, err := time.ActorIDFromBytes(docEvent.Publisher)
if err != nil {
return nil, err
}
Expand All @@ -258,32 +237,12 @@ func FromDocEvent(docEvent *api.DocEvent) (*sync.DocEvent, error) {
return nil, err
}

documentID, err := FromDocumentID(docEvent.DocumentId)
if err != nil {
return nil, err
}

return &sync.DocEvent{
Type: eventType,
Publisher: *client,
DocumentID: documentID,
Type: eventType,
Publisher: client,
}, nil
}

// FromClients converts the given Protobuf formats to model format.
func FromClients(pbClients []*api.Client) ([]*types.Client, error) {
var clients []*types.Client
for _, pbClient := range pbClients {
client, err := FromClient(pbClient)
if err != nil {
return nil, err
}
clients = append(clients, client)
}

return clients, nil
}

// FromOperations converts the given Protobuf formats to model format.
func FromOperations(pbOps []*api.Operation) ([]operations.Operation, error) {
var ops []operations.Operation
Expand Down Expand Up @@ -323,6 +282,53 @@ func FromOperations(pbOps []*api.Operation) ([]operations.Operation, error) {
return ops, nil
}

func fromPresences(pbPresences map[string]*api.Presence) *innerpresence.Map {
presences := innerpresence.NewMap()
for id, pbPresence := range pbPresences {
presences.Store(id, fromPresence(pbPresence))
}
return presences
}

func fromPresence(pbPresence *api.Presence) innerpresence.Presence {
if pbPresence == nil {
return nil
}

data := pbPresence.GetData()
if data == nil {
data = innerpresence.NewPresence()
}

return data
}

// FromPresenceChange converts the given Protobuf formats to model format.
func FromPresenceChange(pbPresenceChange *api.PresenceChange) *innerpresence.PresenceChange {
if pbPresenceChange == nil {
return nil
}

var changeType innerpresence.PresenceChangeType
switch pbPresenceChange.Type {
case api.PresenceChange_CHANGE_TYPE_PUT:
changeType = innerpresence.Put
case api.PresenceChange_CHANGE_TYPE_CLEAR:
changeType = innerpresence.Clear
}

p := innerpresence.PresenceChange{
ChangeType: changeType,
Presence: pbPresenceChange.Presence.Data,
}

if p.ChangeType == innerpresence.Put && p.Presence == nil {
p.Presence = innerpresence.NewPresence()
}

return &p
}

func fromSet(pbSet *api.Operation_Set) (*operations.Set, error) {
parentCreatedAt, err := fromTimeTicket(pbSet.ParentCreatedAt)
if err != nil {
Expand Down
21 changes: 21 additions & 0 deletions api/converter/to_bytes.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,30 @@ import (

api "github.com/yorkie-team/yorkie/api/yorkie/v1"
"github.com/yorkie-team/yorkie/pkg/document/crdt"
"github.com/yorkie-team/yorkie/pkg/document/innerpresence"
"github.com/yorkie-team/yorkie/pkg/index"
)

// SnapshotToBytes converts the given document to byte array.
func SnapshotToBytes(obj *crdt.Object, presences *innerpresence.Map) ([]byte, error) {
pbElem, err := toJSONElement(obj)
if err != nil {
return nil, err
}

pbPresences := ToPresences(presences)

bytes, err := proto.Marshal(&api.Snapshot{
Root: pbElem,
Presences: pbPresences,
})
if err != nil {
return nil, fmt.Errorf("marshal Snapshot to bytes: %w", err)
}

return bytes, nil
}

// ObjectToBytes converts the given object to byte array.
func ObjectToBytes(obj *crdt.Object) ([]byte, error) {
pbElem, err := toJSONElement(obj)
Expand Down
Loading