diff --git a/storage/entity/one.go b/storage/entity/one.go index 96c68e9..e849770 100644 --- a/storage/entity/one.go +++ b/storage/entity/one.go @@ -1,7 +1,16 @@ package entity +import ( + "encoding/json" + "fmt" + "time" + + "go.mongodb.org/mongo-driver/bson" +) + const ( Name = "_id" + JSONName = "name" Relationship = "relationship" Type = "type" Title = "title" @@ -33,3 +42,22 @@ func (o One) Peers() []string { } return names } + +func (o One) MarshalBSON() ([]byte, error) { + if fmt.Sprint(o) != fmt.Sprint(o.Query()) { + o.Modified = time.Now().UnixNano() + } + b, err := json.Marshal(o) + if err != nil { + return nil, err + } + m := bson.M{} + if err := json.Unmarshal(b, &m); err != nil { + return nil, err + } + if name, ok := m[JSONName]; ok { + m[Name] = name + delete(m, JSONName) + } + return bson.Marshal(m) +} diff --git a/storage/entity/one_test.go b/storage/entity/one_test.go index a323d6c..a19f93b 100644 --- a/storage/entity/one_test.go +++ b/storage/entity/one_test.go @@ -3,6 +3,8 @@ package entity import ( "fmt" "testing" + + "go.mongodb.org/mongo-driver/bson" ) func TestOne(t *testing.T) { @@ -15,3 +17,46 @@ func TestOne(t *testing.T) { t.Error(want, q) } } + +func TestOneMarshalBSON(t *testing.T) { + cases := map[string]struct { + sameAsQuery bool + one One + }{ + "query no modified change": { + sameAsQuery: true, + one: (One{Name: "hello", Type: "world", Modified: 1}).Query(), + }, + "modified changes": { + one: (One{Name: "hello", Type: "world", Modified: 1}), + }, + } + + for name, d := range cases { + c := d + t.Run(name, func(t *testing.T) { + var bm bson.Marshaler = c.one + t.Log(bm) + b, err := bson.Marshal(c.one) + if err != nil { + t.Fatal(err) + } + one := One{} + if err := bson.Unmarshal(b, &one); err != nil { + t.Fatal(err) + } + if c.sameAsQuery && (fmt.Sprint(one) != fmt.Sprint(one.Query()) || fmt.Sprint(one) != fmt.Sprint(c.one)) { + t.Error(c.sameAsQuery, c.one, one) + } else if !c.sameAsQuery { + if c.one.Modified == one.Modified { + t.Error(c.one.Modified, one.Modified) + } + c.one.Modified = 0 + one.Modified = 0 + if fmt.Sprint(c.one) != fmt.Sprint(one) { + t.Error(c.one, one) + } + } + }) + } +} diff --git a/storage/graph_test.go b/storage/graph_test.go index 00b7211..60de57e 100644 --- a/storage/graph_test.go +++ b/storage/graph_test.go @@ -85,8 +85,8 @@ func TestIntegration(t *testing.T) { if some[0].Name != ones[0].Name { t.Fatal(some[0].Name) } - if len(some[0].Peers()) > 0 { - t.Fatal(some[0].Peers()) + if l := len(some[0].Peers()); l > 0 { + t.Fatalf("%d: %+v", l, some[0]) } }) diff --git a/storage/operator/modify.go b/storage/operator/modify.go index 9f160e7..c588821 100644 --- a/storage/operator/modify.go +++ b/storage/operator/modify.go @@ -2,6 +2,8 @@ package operator import ( "fmt" + "local/whodunit/storage/entity" + "time" "go.mongodb.org/mongo-driver/bson" ) @@ -51,9 +53,16 @@ func opMarshalable(op, key string, value interface{}) map[string]map[string]inte if len(key) == 0 { return nil } - return map[string]map[string]interface{}{ + m := map[string]map[string]interface{}{ op: map[string]interface{}{ key: value, }, } + if _, ok := m["$set"]; !ok { + m["$set"] = map[string]interface{}{} + } + if _, ok := m["$set"][entity.Modified]; !ok { + m["$set"][entity.Modified] = time.Now().UnixNano() + } + return m }