Skip to content

Commit 90e7ace

Browse files
committed
add gcs migration
1 parent cacc02d commit 90e7ace

1 file changed

Lines changed: 225 additions & 0 deletions

File tree

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
package migration
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"encoding/json"
7+
"fmt"
8+
"io"
9+
10+
"github.com/reearth/reearth/server/internal/app/config"
11+
"github.com/reearth/reearth/server/internal/infrastructure/fs"
12+
"github.com/reearth/reearth/server/internal/infrastructure/gcs"
13+
"github.com/reearth/reearth/server/internal/infrastructure/s3"
14+
"github.com/reearth/reearth/server/internal/usecase/gateway"
15+
"github.com/reearth/reearthx/log"
16+
"github.com/spf13/afero"
17+
"go.mongodb.org/mongo-driver/bson"
18+
)
19+
20+
func GcschangeEsriToDefault(ctx context.Context, c DBClient) error {
21+
22+
conf, cerr := config.ReadConfig(false)
23+
if cerr != nil {
24+
log.Fatalf("failed to load config: %v", cerr)
25+
}
26+
gateway := initFile(ctx, conf)
27+
28+
if err := scenesModify(ctx, c, gateway); err != nil {
29+
fmt.Println("failed to scenesModify:", err)
30+
}
31+
32+
if err := storiesModify(ctx, c, gateway); err != nil {
33+
fmt.Println("failed to storiesModify:", err)
34+
}
35+
36+
return nil
37+
}
38+
39+
func scenesModify(ctx context.Context, c DBClient, gateway gateway.File) error {
40+
41+
collection := c.WithCollection("project").Client()
42+
cur, err := collection.Find(ctx, bson.M{
43+
"publishmentstatus": bson.M{"$in": bson.A{"public", "limited"}},
44+
})
45+
if err != nil {
46+
return err
47+
}
48+
defer func() {
49+
if err := cur.Close(ctx); err != nil {
50+
log.Errorf("failed to close cursor: %v", err)
51+
}
52+
}()
53+
54+
for cur.Next(ctx) {
55+
var doc bson.M
56+
if err := cur.Decode(&doc); err != nil {
57+
continue
58+
}
59+
60+
alias, ok := doc["alias"].(string)
61+
if !ok {
62+
continue
63+
}
64+
65+
rc, err := gateway.ReadBuiltSceneFile(ctx, alias)
66+
if err != nil {
67+
fmt.Println("!!!!!!! failed to ReadBuiltSceneFile:", err)
68+
continue
69+
}
70+
b, err := io.ReadAll(rc)
71+
if err != nil {
72+
fmt.Println("!!!!!!! read error")
73+
continue
74+
}
75+
if !json.Valid(b) {
76+
fmt.Println("!!!!!!! invalid JSON")
77+
continue
78+
}
79+
80+
var sceneData map[string]interface{}
81+
if err := json.Unmarshal(b, &sceneData); err != nil {
82+
fmt.Println("!!!!!!! failed to unmarshal JSON:", err)
83+
continue
84+
}
85+
86+
if changed := change(sceneData); changed {
87+
updatedJSON, err := json.MarshalIndent(sceneData, "", " ")
88+
if err != nil {
89+
fmt.Println("!!!!!!! failed to marshal updated JSON:", err)
90+
continue
91+
}
92+
93+
fmt.Printf("Updated scene for alias %s:\n%s\n", alias, string(updatedJSON))
94+
95+
updatedReader := bytes.NewReader(updatedJSON)
96+
if err = gateway.UploadBuiltScene(ctx, updatedReader, alias); err != nil {
97+
fmt.Println(fmt.Errorf("!!!!!!! failed to upload updated scene for alias %s: %v", alias, err))
98+
continue
99+
}
100+
101+
log.Printf("Successfully updated tile_type from esri_world_topo to default for alias: %s", alias)
102+
103+
}
104+
}
105+
106+
return nil
107+
}
108+
109+
func storiesModify(ctx context.Context, c DBClient, gateway gateway.File) error {
110+
111+
collection := c.WithCollection("storytelling").Client()
112+
cur, err := collection.Find(ctx, bson.M{
113+
"status": bson.M{"$in": bson.A{"public", "limited"}},
114+
})
115+
if err != nil {
116+
return err
117+
}
118+
119+
defer func() {
120+
if err := cur.Close(ctx); err != nil {
121+
log.Errorf("failed to close cursor: %v", err)
122+
}
123+
}()
124+
125+
for cur.Next(ctx) {
126+
var doc bson.M
127+
if err := cur.Decode(&doc); err != nil {
128+
continue
129+
}
130+
131+
alias, ok := doc["alias"].(string)
132+
if !ok {
133+
continue
134+
}
135+
136+
rc, err := gateway.ReadStoryFile(ctx, alias)
137+
if err != nil {
138+
fmt.Println("!!!!!!! failed to ReadBuiltSceneFile:", err)
139+
continue
140+
}
141+
b, err := io.ReadAll(rc)
142+
if err != nil {
143+
fmt.Println("!!!!!!! read error")
144+
continue
145+
}
146+
if !json.Valid(b) {
147+
fmt.Println("!!!!!!! invalid JSON")
148+
continue
149+
}
150+
151+
var storyData map[string]interface{}
152+
if err := json.Unmarshal(b, &storyData); err != nil {
153+
fmt.Println("!!!!!!! failed to unmarshal JSON:", err)
154+
continue
155+
}
156+
157+
if changed := change(storyData); changed {
158+
updatedJSON, err := json.MarshalIndent(storyData, "", " ")
159+
if err != nil {
160+
fmt.Println("!!!!!!! failed to marshal updated JSON:", err)
161+
continue
162+
}
163+
164+
fmt.Printf("Updated story for alias %s:\n%s\n", alias, string(updatedJSON))
165+
166+
updatedReader := bytes.NewReader(updatedJSON)
167+
if err = gateway.UploadStory(ctx, updatedReader, alias); err != nil {
168+
fmt.Println(fmt.Errorf("!!!!!!! failed to upload updated story for alias %s: %v", alias, err))
169+
continue
170+
}
171+
172+
log.Printf("Successfully updated tile_type from esri_world_topo to default for alias: %s", alias)
173+
174+
}
175+
}
176+
177+
return nil
178+
}
179+
180+
func change(data map[string]interface{}) bool {
181+
modified := false
182+
if property, ok := data["property"].(map[string]interface{}); ok {
183+
if tiles, ok := property["tiles"].([]interface{}); ok {
184+
for _, tile := range tiles {
185+
if tileMap, ok := tile.(map[string]interface{}); ok {
186+
if tileType, ok := tileMap["tile_type"].(string); ok && tileType == "esri_world_topo" {
187+
tileMap["tile_type"] = "default"
188+
modified = true
189+
}
190+
}
191+
}
192+
}
193+
}
194+
return modified
195+
}
196+
197+
func initFile(ctx context.Context, conf *config.Config) (fileRepo gateway.File) {
198+
var err error
199+
if conf.GCS.IsConfigured() {
200+
log.Infofc(ctx, "file: GCS storage is used: %s\n", conf.GCS.BucketName)
201+
fileRepo, err = gcs.NewFile(conf.GCS.BucketName, conf.AssetBaseURL, conf.GCS.PublicationCacheControl)
202+
if err != nil {
203+
log.Warnf("file: failed to init GCS storage: %s\n", err.Error())
204+
}
205+
return
206+
207+
}
208+
209+
if conf.S3.IsConfigured() {
210+
log.Infofc(ctx, "file: S3 storage is used: %s\n", conf.S3.BucketName)
211+
fileRepo, err = s3.NewS3(ctx, conf.S3.BucketName, conf.AssetBaseURL, conf.S3.PublicationCacheControl)
212+
if err != nil {
213+
log.Warnf("file: failed to init S3 storage: %s\n", err.Error())
214+
}
215+
return
216+
}
217+
218+
log.Infof("file: local storage is used")
219+
afs := afero.NewBasePathFs(afero.NewOsFs(), "data")
220+
fileRepo, err = fs.NewFile(afs, conf.AssetBaseURL)
221+
if err != nil {
222+
log.Fatalf("file: init error: %+v", err)
223+
}
224+
return fileRepo
225+
}

0 commit comments

Comments
 (0)