Skip to content

Commit 4249aac

Browse files
committed
feat(engine): prepare an endpoint to generate schema diff
1 parent e261000 commit 4249aac

File tree

4 files changed

+94
-1
lines changed

4 files changed

+94
-1
lines changed

engine/cmd/database-lab/main.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"gitlab.com/postgres-ai/database-lab/v3/internal/provision/runners"
3232
"gitlab.com/postgres-ai/database-lab/v3/internal/retrieval"
3333
"gitlab.com/postgres-ai/database-lab/v3/internal/retrieval/engine/postgres/tools/cont"
34+
"gitlab.com/postgres-ai/database-lab/v3/internal/schema"
3435
"gitlab.com/postgres-ai/database-lab/v3/internal/srv"
3536
"gitlab.com/postgres-ai/database-lab/v3/internal/telemetry"
3637
"gitlab.com/postgres-ai/database-lab/v3/pkg/config"
@@ -153,7 +154,9 @@ func main() {
153154
})
154155

155156
embeddedUI := embeddedui.New(cfg.EmbeddedUI, engProps, runner, docker)
156-
server := srv.NewServer(&cfg.Server, &cfg.Global, engProps, docker, cloningSvc, provisioner, retrievalSvc, platformSvc, obs, est, pm, tm)
157+
schemaDiff := schema.NewDiff(docker)
158+
server := srv.NewServer(&cfg.Server, &cfg.Global, engProps, docker, cloningSvc, provisioner, retrievalSvc, platformSvc,
159+
obs, est, schemaDiff, pm, tm)
157160
shutdownCh := setShutdownListener()
158161

159162
go setReloadListener(ctx, provisioner, tm, retrievalSvc, pm, cloningSvc, platformSvc, est, embeddedUI, server)

engine/internal/schema/schema.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Package schema provides tools to manage PostgreSQL schemas difference.
2+
package schema
3+
4+
import (
5+
"github.com/docker/docker/client"
6+
7+
"gitlab.com/postgres-ai/database-lab/v3/pkg/models"
8+
)
9+
10+
// Diff defines a schema generator.
11+
type Diff struct {
12+
d *client.Client
13+
}
14+
15+
// NewDiff creates a new Diff service.
16+
func NewDiff(d *client.Client) *Diff {
17+
return &Diff{d: d}
18+
}
19+
20+
// GenerateDiff generate difference between database schemas.
21+
func (d *Diff) GenerateDiff(actual, origin *models.Clone) (string, error) {
22+
return "", nil
23+
}

engine/internal/srv/routes.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/gorilla/websocket"
1414
"github.com/jackc/pgtype/pgxtype"
1515
"github.com/pkg/errors"
16+
"github.com/sethvargo/go-password/password"
1617

1718
"gitlab.com/postgres-ai/database-lab/v3/internal/estimator"
1819
"gitlab.com/postgres-ai/database-lab/v3/internal/observer"
@@ -529,6 +530,67 @@ func (s *Server) downloadArtifact(w http.ResponseWriter, r *http.Request) {
529530
http.ServeFile(w, r, filePath)
530531
}
531532

533+
func (s *Server) schemaDiff(w http.ResponseWriter, r *http.Request) {
534+
cloneID := mux.Vars(r)["clone_id"]
535+
536+
if cloneID == "" {
537+
api.SendBadRequestError(w, r, "Clone ID must not be empty")
538+
return
539+
}
540+
541+
clone, err := s.Cloning.GetClone(cloneID)
542+
if err != nil {
543+
api.SendNotFoundError(w, r)
544+
return
545+
}
546+
547+
const (
548+
PasswordLength = 16
549+
PasswordMinDigits = 4
550+
PasswordMinSymbols = 0
551+
)
552+
553+
pwd, err := password.Generate(PasswordLength, PasswordMinDigits, PasswordMinSymbols, false, true)
554+
if err != nil {
555+
api.SendError(w, r, fmt.Errorf("failed to generate a password to a reference clone: %w", err))
556+
return
557+
}
558+
559+
originClone, err := s.Cloning.CreateClone(&types.CloneCreateRequest{
560+
ID: "diff-" + cloneID,
561+
DB: &types.DatabaseRequest{
562+
Username: clone.DB.Username,
563+
DBName: clone.DB.DBName,
564+
Password: pwd,
565+
},
566+
Snapshot: &types.SnapshotCloneFieldRequest{ID: clone.Snapshot.ID},
567+
})
568+
if err != nil {
569+
api.SendError(w, r, fmt.Errorf("cannot create a clone based on snapshot %s: %w", clone.Snapshot.ID, err))
570+
return
571+
}
572+
573+
defer func() {
574+
if err := s.Cloning.DestroyClone(originClone.ID); err != nil {
575+
log.Err("Failed to destroy origin clone:", err)
576+
}
577+
}()
578+
579+
diff, err := s.SchemaDiff.GenerateDiff(clone, originClone)
580+
if err != nil {
581+
api.SendError(w, r, fmt.Errorf("cannot generate schema diff: %w", err))
582+
return
583+
}
584+
585+
w.Header().Set("Content-Type", "plain/text; charset=utf-8")
586+
w.WriteHeader(http.StatusOK)
587+
588+
if _, err := w.Write([]byte(diff)); err != nil {
589+
api.SendError(w, r, err)
590+
return
591+
}
592+
}
593+
532594
// healthCheck provides a health check handler.
533595
func (s *Server) healthCheck(w http.ResponseWriter, _ *http.Request) {
534596
w.Header().Set("Content-Type", "application/json; charset=utf-8")

engine/internal/srv/server.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"gitlab.com/postgres-ai/database-lab/v3/internal/provision"
2626
"gitlab.com/postgres-ai/database-lab/v3/internal/provision/pool"
2727
"gitlab.com/postgres-ai/database-lab/v3/internal/retrieval"
28+
"gitlab.com/postgres-ai/database-lab/v3/internal/schema"
2829
"gitlab.com/postgres-ai/database-lab/v3/internal/srv/api"
2930
srvCfg "gitlab.com/postgres-ai/database-lab/v3/internal/srv/config"
3031
"gitlab.com/postgres-ai/database-lab/v3/internal/srv/mw"
@@ -49,6 +50,7 @@ type Server struct {
4950
Platform *platform.Service
5051
Observer *observer.Observer
5152
Estimator *estimator.Estimator
53+
SchemaDiff *schema.Diff
5254
upgrader websocket.Upgrader
5355
httpSrv *http.Server
5456
docker *client.Client
@@ -67,6 +69,7 @@ func NewServer(cfg *srvCfg.Config, globalCfg *global.Config,
6769
platform *platform.Service,
6870
observer *observer.Observer,
6971
estimator *estimator.Estimator,
72+
schemaDiff *schema.Diff,
7073
pm *pool.Manager,
7174
tm *telemetry.Agent) *Server {
7275
server := &Server{
@@ -79,6 +82,7 @@ func NewServer(cfg *srvCfg.Config, globalCfg *global.Config,
7982
Platform: platform,
8083
Observer: observer,
8184
Estimator: estimator,
85+
SchemaDiff: schemaDiff,
8286
upgrader: websocket.Upgrader{},
8387
docker: dockerClient,
8488
pm: pm,
@@ -177,6 +181,7 @@ func (s *Server) InitHandlers() {
177181
r.HandleFunc("/clone/{id}", authMW.Authorized(s.getClone)).Methods(http.MethodGet)
178182
r.HandleFunc("/clone/{id}/reset", authMW.Authorized(s.resetClone)).Methods(http.MethodPost)
179183
r.HandleFunc("/clone/{id}", authMW.Authorized(s.getClone)).Methods(http.MethodGet)
184+
r.HandleFunc("/clone/diff/{clone_id}", authMW.Authorized(s.schemaDiff)).Methods(http.MethodGet)
180185
r.HandleFunc("/observation/start", authMW.Authorized(s.startObservation)).Methods(http.MethodPost)
181186
r.HandleFunc("/observation/stop", authMW.Authorized(s.stopObservation)).Methods(http.MethodPost)
182187
r.HandleFunc("/observation/summary/{clone_id}/{session_id}", authMW.Authorized(s.sessionSummaryObservation)).Methods(http.MethodGet)

0 commit comments

Comments
 (0)