Skip to content

Commit 2476e5e

Browse files
committed
add gcs migration
1 parent cacc02d commit 2476e5e

1 file changed

Lines changed: 220 additions & 0 deletions

File tree

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
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+
defer cur.Close(ctx)
119+
120+
for cur.Next(ctx) {
121+
var doc bson.M
122+
if err := cur.Decode(&doc); err != nil {
123+
continue
124+
}
125+
126+
alias, ok := doc["alias"].(string)
127+
if !ok {
128+
continue
129+
}
130+
131+
rc, err := gateway.ReadStoryFile(ctx, alias)
132+
if err != nil {
133+
fmt.Println("!!!!!!! failed to ReadBuiltSceneFile:", err)
134+
continue
135+
}
136+
b, err := io.ReadAll(rc)
137+
if err != nil {
138+
fmt.Println("!!!!!!! read error")
139+
continue
140+
}
141+
if !json.Valid(b) {
142+
fmt.Println("!!!!!!! invalid JSON")
143+
continue
144+
}
145+
146+
var storyData map[string]interface{}
147+
if err := json.Unmarshal(b, &storyData); err != nil {
148+
fmt.Println("!!!!!!! failed to unmarshal JSON:", err)
149+
continue
150+
}
151+
152+
if changed := change(storyData); changed {
153+
updatedJSON, err := json.MarshalIndent(storyData, "", " ")
154+
if err != nil {
155+
fmt.Println("!!!!!!! failed to marshal updated JSON:", err)
156+
continue
157+
}
158+
159+
fmt.Printf("Updated story for alias %s:\n%s\n", alias, string(updatedJSON))
160+
161+
updatedReader := bytes.NewReader(updatedJSON)
162+
if err = gateway.UploadStory(ctx, updatedReader, alias); err != nil {
163+
fmt.Println(fmt.Errorf("!!!!!!! failed to upload updated story for alias %s: %v", alias, err))
164+
continue
165+
}
166+
167+
log.Printf("Successfully updated tile_type from esri_world_topo to default for alias: %s", alias)
168+
169+
}
170+
}
171+
172+
return nil
173+
}
174+
175+
func change(data map[string]interface{}) bool {
176+
modified := false
177+
if property, ok := data["property"].(map[string]interface{}); ok {
178+
if tiles, ok := property["tiles"].([]interface{}); ok {
179+
for _, tile := range tiles {
180+
if tileMap, ok := tile.(map[string]interface{}); ok {
181+
if tileType, ok := tileMap["tile_type"].(string); ok && tileType == "esri_world_topo" {
182+
tileMap["tile_type"] = "default"
183+
modified = true
184+
}
185+
}
186+
}
187+
}
188+
}
189+
return modified
190+
}
191+
192+
func initFile(ctx context.Context, conf *config.Config) (fileRepo gateway.File) {
193+
var err error
194+
if conf.GCS.IsConfigured() {
195+
log.Infofc(ctx, "file: GCS storage is used: %s\n", conf.GCS.BucketName)
196+
fileRepo, err = gcs.NewFile(conf.GCS.BucketName, conf.AssetBaseURL, conf.GCS.PublicationCacheControl)
197+
if err != nil {
198+
log.Warnf("file: failed to init GCS storage: %s\n", err.Error())
199+
}
200+
return
201+
202+
}
203+
204+
if conf.S3.IsConfigured() {
205+
log.Infofc(ctx, "file: S3 storage is used: %s\n", conf.S3.BucketName)
206+
fileRepo, err = s3.NewS3(ctx, conf.S3.BucketName, conf.AssetBaseURL, conf.S3.PublicationCacheControl)
207+
if err != nil {
208+
log.Warnf("file: failed to init S3 storage: %s\n", err.Error())
209+
}
210+
return
211+
}
212+
213+
log.Infof("file: local storage is used")
214+
afs := afero.NewBasePathFs(afero.NewOsFs(), "data")
215+
fileRepo, err = fs.NewFile(afs, conf.AssetBaseURL)
216+
if err != nil {
217+
log.Fatalf("file: init error: %+v", err)
218+
}
219+
return fileRepo
220+
}

0 commit comments

Comments
 (0)