Skip to content
This repository has been archived by the owner on Aug 16, 2022. It is now read-only.

feat: automatic property migration from old schema to new schema #85

Closed
wants to merge 56 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
522a88d
rename value.OptionalValue
rot1024 Nov 29, 2021
9039174
add cast method
rot1024 Nov 29, 2021
9b8a7ed
add Pointer, GraphPointer, Migrator to dataset
rot1024 Dec 1, 2021
b5e6526
fix dataset
rot1024 Dec 2, 2021
0c760d2
use dataset.GraphPointer as property link
rot1024 Dec 2, 2021
1922006
add cast method to property.Value, change value.Optional.Cast, add tests
rot1024 Dec 6, 2021
1411aa4
add property id
rot1024 Dec 6, 2021
66eecf2
enhance value converting
rot1024 Dec 6, 2021
76318e7
add Cast to property.Field
rot1024 Dec 6, 2021
21501be
add GroupAndFields, GroupAndField to property.Schema
rot1024 Dec 7, 2021
708ab9d
fix test
rot1024 Dec 7, 2021
4f53aea
add property.SchemaGroupList
rot1024 Dec 7, 2021
d842430
rename CollectDatasets
rot1024 Dec 7, 2021
f353372
remove extra fields from property.Item
rot1024 Dec 7, 2021
54a804d
add Clone, Fields, RemoveFields to property
rot1024 Dec 7, 2021
51f05e6
rename GetGroup
rot1024 Dec 8, 2021
c9cef8a
add MoveFields to property
rot1024 Dec 10, 2021
4962449
remove property.FieldUnsafeBuilder
rot1024 Dec 10, 2021
e7e2f71
return nil from id.ID.Ref if id is nil
rot1024 Dec 10, 2021
bad7e5c
fix rerror test
rot1024 Dec 10, 2021
f5f9512
delete schema field in property.Item, delete IDRef method
rot1024 Dec 10, 2021
459fe9c
separate SchemaFieldPointer
rot1024 Dec 13, 2021
e90ad94
RemoveFields returns bool
rot1024 Dec 13, 2021
4086dd0
add GroupAndFields method
rot1024 Dec 13, 2021
e2e1b8e
add FieldBySchemaFieldPointer to property.SchemaGroup
rot1024 Dec 13, 2021
0bc7633
Add SchemaFieldPointer method to SchemaGroupAndField
rot1024 Dec 13, 2021
e6dbd12
fix PluginID.IsNil
rot1024 Dec 13, 2021
7e0123d
add Cast method to property
rot1024 Dec 13, 2021
6d86996
property.Prune returns bool
rot1024 Dec 13, 2021
c1ea4d6
add GuessSchema method
rot1024 Dec 14, 2021
6865e3b
impl property.SchemaDiff
rot1024 Dec 14, 2021
337a2bd
GroupAndFields accepts pointer
rot1024 Dec 14, 2021
4ca9d0d
fix property.Field.Cast
rot1024 Dec 14, 2021
9290f69
update property.MoveFields, add tests
rot1024 Dec 14, 2021
c4c1dd3
impl SchemaDiff.Migrate (wip)
rot1024 Dec 14, 2021
89743d1
add GetOrCreateRootGroup to property
rot1024 Dec 15, 2021
126f0ee
update property.MoveFields
rot1024 Dec 15, 2021
396883d
add id fields, IsEmpty to property.Diff
rot1024 Dec 15, 2021
278ebf1
add schema loader initializers
rot1024 Dec 15, 2021
5ced283
refactor and add nil check to plugin
rot1024 Dec 15, 2021
256c9a9
impl plugin/manifest.Diff
rot1024 Dec 15, 2021
49b53de
add property.SchemaDiff.IsPropertySchemaChanged
rot1024 Dec 23, 2021
9d15e89
add property.List.IDs
rot1024 Dec 23, 2021
131b1d7
rename property.SchemaDiff.IsPropertySchemaChanged
rot1024 Dec 23, 2021
fd20d7f
add DeletedPropertySchemas and PropertySchmaDiffs to manifest.Diff
rot1024 Dec 23, 2021
9a1b631
update scene.PluginSystem.Upgrade
rot1024 Dec 23, 2021
64cf1c0
add FindBySchema to repo.Property
rot1024 Dec 23, 2021
d89ecc7
add IDs to layer.List
rot1024 Dec 23, 2021
74dee49
add Properties method to pkg/layer.List
rot1024 Jan 12, 2022
87c94bb
refactor mongo and add indexes
rot1024 Jan 12, 2022
ebea1cb
layer.IDList.RemoveLayer accepts multiple layers
rot1024 Jan 12, 2022
121cd3f
update schema in property on migration
rot1024 Jan 12, 2022
05de899
rename and refactor scene.PluginSystem
rot1024 Jan 12, 2022
4455540
impl usecase
rot1024 Jan 12, 2022
1576309
fix mocking NewItemID
rot1024 Jan 13, 2022
4f8ef14
Merge branch 'main' of https://github.com/reearth/reearth-backend int…
rot1024 Jan 13, 2022
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
41 changes: 21 additions & 20 deletions internal/adapter/gql/gqlmodel/convert_property.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package gqlmodel
import (
"strings"

"github.com/reearth/reearth-backend/pkg/dataset"
"github.com/reearth/reearth-backend/pkg/id"
"github.com/reearth/reearth-backend/pkg/property"
"github.com/reearth/reearth-backend/pkg/value"
Expand Down Expand Up @@ -122,7 +123,7 @@ func ToPropertyField(f *property.Field, parent *property.Property, gl *property.
var links []*PropertyFieldLink
if flinks := f.Links(); flinks != nil {
links = make([]*PropertyFieldLink, 0, flinks.Len())
for _, l := range flinks.Links() {
for _, l := range flinks.Pointers() {
links = append(links, ToPropertyFieldLink(l))
}
}
Expand All @@ -138,24 +139,24 @@ func ToPropertyField(f *property.Field, parent *property.Property, gl *property.
}
}

func ToPropertyFieldLinks(flinks *property.Links) []*PropertyFieldLink {
func ToPropertyFieldLinks(flinks *dataset.GraphPointer) []*PropertyFieldLink {
if flinks == nil {
return nil
}
var links []*PropertyFieldLink
links = make([]*PropertyFieldLink, 0, flinks.Len())
for _, l := range flinks.Links() {
for _, l := range flinks.Pointers() {
links = append(links, ToPropertyFieldLink(l))
}
return links
}

func FromPropertyFieldLink(datasetSchema, ds, fields []*id.ID) *property.Links {
func FromPropertyFieldLink(datasetSchema, ds, fields []*id.ID) *dataset.GraphPointer {
if len(datasetSchema) != len(fields) || (ds != nil && len(ds) != len(fields) && len(ds) > 1) {
return nil
}

links := make([]*property.Link, 0, len(datasetSchema))
links := make([]*dataset.Pointer, 0, len(datasetSchema))
for i, dss := range datasetSchema {
f := fields[i]
if dss == nil || f == nil {
Expand All @@ -164,24 +165,24 @@ func FromPropertyFieldLink(datasetSchema, ds, fields []*id.ID) *property.Links {
dsid := id.DatasetSchemaID(*dss)
dsfid := id.DatasetSchemaFieldID(*f)
if len(ds) == 0 || (len(ds) == 1 && i > 0) {
links = append(links, property.NewLinkFieldOnly(dsid, dsfid))
links = append(links, dataset.PointAtField(dsid, dsfid))
} else {
d := ds[i]
if d == nil {
return nil
}
links = append(links, property.NewLink(id.DatasetID(*d), dsid, dsfid))
links = append(links, dataset.PointAt(id.DatasetID(*d), dsid, dsfid))
}
}

return property.NewLinks(links)
return dataset.NewGraphPointer(links)
}

func ToPropertyFieldLink(link *property.Link) *PropertyFieldLink {
func ToPropertyFieldLink(link *dataset.Pointer) *PropertyFieldLink {
return &PropertyFieldLink{
DatasetID: link.Dataset().IDRef(),
DatasetSchemaID: link.DatasetSchema().ID(),
DatasetSchemaFieldID: link.DatasetSchemaField().ID(),
DatasetSchemaID: link.Schema().ID(),
DatasetSchemaFieldID: link.Field().ID(),
}
}

Expand All @@ -208,10 +209,10 @@ func ToPropertySchema(propertySchema *property.Schema) *PropertySchema {
return nil
}

pgroups := propertySchema.Groups()
pgroups := propertySchema.Groups().Groups()
groups := make([]*PropertySchemaGroup, 0, len(pgroups))
for _, g := range pgroups {
groups = append(groups, ToPropertySchemaGroup(g))
groups = append(groups, ToPropertySchemaGroup(g, propertySchema.ID()))
}

return &PropertySchema{
Expand All @@ -224,8 +225,8 @@ func ToPropertySchema(propertySchema *property.Schema) *PropertySchema {
func ToPropertyLinkableFields(sid id.PropertySchemaID, l property.LinkableFields) *PropertyLinkableFields {
return &PropertyLinkableFields{
SchemaID: sid,
Latlng: l.LatLng.FieldRef(),
URL: l.URL.FieldRef(),
Latlng: l.FieldByType(property.ValueTypeLatLng),
URL: l.FieldByType(property.ValueTypeURL),
}
}

Expand Down Expand Up @@ -364,7 +365,7 @@ func ToMergedPropertyField(f *property.MergedField, s id.PropertySchemaID) *Merg
}
}

func ToPropertySchemaGroup(g *property.SchemaGroup) *PropertySchemaGroup {
func ToPropertySchemaGroup(g *property.SchemaGroup, p property.SchemaID) *PropertySchemaGroup {
if g == nil {
return nil
}
Expand All @@ -381,7 +382,7 @@ func ToPropertySchemaGroup(g *property.SchemaGroup) *PropertySchemaGroup {
}
return &PropertySchemaGroup{
SchemaGroupID: g.ID(),
SchemaID: g.Schema(),
SchemaID: p,
IsList: g.IsList(),
Title: g.Title().StringRef(),
Fields: fields,
Expand All @@ -397,15 +398,15 @@ func ToPropertyGroup(g *property.Group, p *property.Property, gl *property.Group
return nil
}

gfields := g.Fields()
gfields := g.Fields(nil)
fields := make([]*PropertyField, 0, len(gfields))
for _, f := range gfields {
fields = append(fields, ToPropertyField(f, p, gl, g))
}

return &PropertyGroup{
ID: g.ID().ID(),
SchemaID: g.Schema(),
SchemaID: p.Schema(),
SchemaGroupID: g.SchemaGroup(),
Fields: fields,
}
Expand All @@ -424,7 +425,7 @@ func ToPropertyGroupList(g *property.GroupList, p *property.Property) *PropertyG

return &PropertyGroupList{
ID: g.ID().ID(),
SchemaID: g.Schema(),
SchemaID: p.Schema(),
SchemaGroupID: g.SchemaGroup(),
Groups: groups,
}
Expand Down
2 changes: 1 addition & 1 deletion internal/adapter/gql/gqlmodel/convert_scene.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func ToScene(scene *scene.Scene) *Scene {
clusters = append(clusters, ToCluster(c))
}

scenePlugins := scene.PluginSystem().Plugins()
scenePlugins := scene.Plugins().Plugins()
plugins := make([]*ScenePlugin, 0, len(scenePlugins))
for _, sp := range scenePlugins {
plugins = append(plugins, ToScenePlugin(sp))
Expand Down
4 changes: 2 additions & 2 deletions internal/adapter/gql/resolver_mutation_scene.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ func (r *mutationResolver) UploadPlugin(ctx context.Context, input gqlmodel.Uplo
return &gqlmodel.UploadPluginPayload{
Plugin: gqlmodel.ToPlugin(p),
Scene: gqlmodel.ToScene(s),
ScenePlugin: gqlmodel.ToScenePlugin(s.PluginSystem().Plugin(p.ID())),
ScenePlugin: gqlmodel.ToScenePlugin(s.Plugins().Plugin(p.ID())),
}, nil
}

Expand Down Expand Up @@ -192,7 +192,7 @@ func (r *mutationResolver) UpgradePlugin(ctx context.Context, input gqlmodel.Upg

return &gqlmodel.UpgradePluginPayload{
Scene: gqlmodel.ToScene(s),
ScenePlugin: gqlmodel.ToScenePlugin(s.PluginSystem().Plugin(input.ToPluginID)),
ScenePlugin: gqlmodel.ToScenePlugin(s.Plugins().Plugin(input.ToPluginID)),
}, nil
}

Expand Down
32 changes: 22 additions & 10 deletions internal/infrastructure/github/plugin_registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package github

import (
"context"
"errors"
"testing"
"time"

Expand All @@ -19,8 +18,16 @@ func TestNewPluginRegistry(t *testing.T) {
func TestPluginRegistry_FetchMetadata(t *testing.T) {
httpmock.Activate()
defer httpmock.DeactivateAndReset()
httpmock.RegisterResponder("GET", "https://raw.githubusercontent.com/reearth/plugins/main/plugins.json",
httpmock.NewStringResponder(200, `[{"name": "reearth","description": "Official Plugin", "author": "reearth", "thumbnailUrl": "", "createdAt": "2021-03-16T04:19:57.592Z"}]`))

httpmock.RegisterResponder(
"GET",
"https://raw.githubusercontent.com/reearth/plugins/main/plugins.json",
httpmock.NewStringResponder(
200,
`[{"name": "reearth","description": "Official Plugin", "author": "reearth", "thumbnailUrl": "", "createdAt": "2021-03-16T04:19:57.592Z"}]`,
),
)

d := NewPluginRegistry()
res, err := d.FetchMetadata(context.Background())
tm, _ := time.Parse(time.RFC3339, "2021-03-16T04:19:57.592Z")
Expand All @@ -37,15 +44,20 @@ func TestPluginRegistry_FetchMetadata(t *testing.T) {
assert.NoError(t, err)

// fail: bad request
httpmock.RegisterResponder("GET", "https://raw.githubusercontent.com/reearth/plugins/main/plugins.json",
httpmock.NewStringResponder(400, `mock bad request`))
httpmock.RegisterResponder(
"GET",
"https://raw.githubusercontent.com/reearth/plugins/main/plugins.json",
httpmock.NewStringResponder(400, `mock bad request`),
)
_, err = d.FetchMetadata(context.Background())
assert.True(t, errors.As(errors.New("StatusCode=400"), &err))
assert.EqualError(t, err, "StatusCode=400")

// fail: unable to marshal
httpmock.RegisterResponder("GET", "https://raw.githubusercontent.com/reearth/plugins/main/plugins.json",
httpmock.NewStringResponder(200, `{"hoge": "test"}`))
httpmock.RegisterResponder(
"GET",
"https://raw.githubusercontent.com/reearth/plugins/main/plugins.json",
httpmock.NewStringResponder(200, `{"hoge": "test"}`),
)
_, err = d.FetchMetadata(context.Background())
assert.True(t, errors.As(errors.New("cannot unmarshal object into Go value of type []*plugin.Metadata"), &err))

assert.Error(t, err)
}
44 changes: 44 additions & 0 deletions internal/infrastructure/memory/layer.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,50 @@ func (r *Layer) FindGroupBySceneAndLinkedDatasetSchema(ctx context.Context, s id
return result, nil
}

func (r *Layer) FindParentsByIDs(_ context.Context, ids []id.LayerID, scenes []id.SceneID) (layer.GroupList, error) {
r.lock.Lock()
defer r.lock.Unlock()

res := layer.GroupList{}
for _, l := range r.data {
if !isSceneIncludes(l.Scene(), scenes) {
continue
}
gl, ok := l.(*layer.Group)
if !ok {
continue
}
for _, cl := range gl.Layers().Layers() {
if cl.Contains(ids) {
res = append(res, gl)
}
}
}

return res, nil
}

func (r *Layer) FindByPluginAndExtension(_ context.Context, pid id.PluginID, eid *id.PluginExtensionID, scenes []id.SceneID) (layer.List, error) {
r.lock.Lock()
defer r.lock.Unlock()

res := layer.List{}
for _, l := range r.data {
if !isSceneIncludes(l.Scene(), scenes) {
continue
}

if l.Plugin().Equal(pid) {
e := l.Extension()
if eid == nil || e != nil && *e == *eid {
res = append(res, &l)
}
}
}

return res, nil
}

func (r *Layer) FindByProperty(ctx context.Context, id id.PropertyID, f []id.SceneID) (layer.Layer, error) {
r.lock.Lock()
defer r.lock.Unlock()
Expand Down
24 changes: 24 additions & 0 deletions internal/infrastructure/memory/property.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package memory

import (
"context"
"sort"
"sync"

"github.com/reearth/reearth-backend/pkg/id"
Expand Down Expand Up @@ -80,6 +81,29 @@ func (r *Property) FindLinkedAll(ctx context.Context, s id.SceneID) (property.Li
return result, nil
}

func (r *Property) FindBySchema(_ context.Context, schemas []id.PropertySchemaID, s id.SceneID) (property.List, error) {
r.lock.Lock()
defer r.lock.Unlock()

result := property.List{}
for _, p := range r.data {
if p.Scene() != s {
continue
}
for _, s := range schemas {
if p.Schema().Equal(s) {
p2 := p
result = append(result, &p2)
break
}
}
}
sort.Slice(result, func(i, j int) bool {
return result[i].ID().ID().Compare(result[j].ID().ID()) < 0
})
return result, nil
}

func (r *Property) Save(ctx context.Context, p *property.Property) error {
r.lock.Lock()
defer r.lock.Unlock()
Expand Down
69 changes: 69 additions & 0 deletions internal/infrastructure/memory/property_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package memory

import (
"context"
"testing"

"github.com/reearth/reearth-backend/pkg/id"
"github.com/reearth/reearth-backend/pkg/property"
"github.com/stretchr/testify/assert"
)

func TestProperty_FindBySchema(t *testing.T) {
p1 := id.NewPropertyID()
p2 := id.NewPropertyID()
p3 := id.NewPropertyID()
p4 := id.NewPropertyID()
p5 := id.NewPropertyID()
ps1 := id.MustPropertySchemaID("a~1.0.0/a")
ps2 := id.MustPropertySchemaID("a~1.0.0/b")
s1 := id.NewSceneID()
s2 := id.NewSceneID()

type args struct {
in0 context.Context
schemas []id.PropertySchemaID
s id.SceneID
}
tests := []struct {
name string
target *Property
args args
want property.List
wantErr error
}{
{
name: "found",
target: &Property{
data: map[id.PropertyID]property.Property{
p1: *property.New().ID(p1).Scene(s1).Schema(ps1).MustBuild(),
p2: *property.New().ID(p2).Scene(s1).Schema(ps2).MustBuild(),
p3: *property.New().ID(p3).Scene(s2).Schema(ps1).MustBuild(),
p4: *property.New().ID(p4).Scene(s2).Schema(ps2).MustBuild(),
p5: *property.New().ID(p5).Scene(s1).Schema(ps1).MustBuild(),
},
},
args: args{
in0: nil,
schemas: []id.PropertySchemaID{ps1, ps2},
s: s1,
},
want: property.List{
property.New().ID(p1).Scene(s1).Schema(ps1).MustBuild(),
property.New().ID(p2).Scene(s1).Schema(ps2).MustBuild(),
property.New().ID(p5).Scene(s1).Schema(ps1).MustBuild(),
},
wantErr: nil,
},
}

for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got, err := tt.target.FindBySchema(tt.args.in0, tt.args.schemas, tt.args.s)
assert.Equal(t, tt.wantErr, err)
assert.Equal(t, tt.want, got)
})
}
}
Loading