github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/sqle/cluster/initdbhook.go (about) 1 // Copyright 2022 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package cluster 16 17 import ( 18 "context" 19 "fmt" 20 "strings" 21 22 "github.com/dolthub/go-mysql-server/sql" 23 24 "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" 25 "github.com/dolthub/dolt/go/libraries/doltcore/env" 26 "github.com/dolthub/dolt/go/libraries/doltcore/sqle" 27 "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess" 28 "github.com/dolthub/dolt/go/store/types" 29 ) 30 31 func NewInitDatabaseHook(controller *Controller, bt *sql.BackgroundThreads) sqle.InitDatabaseHook { 32 return func(ctx *sql.Context, pro *sqle.DoltDatabaseProvider, name string, denv *env.DoltEnv, db dsess.SqlDatabase) error { 33 dialprovider := controller.gRPCDialProvider(denv) 34 var remoteDBs []func(context.Context) (*doltdb.DoltDB, error) 35 var remoteUrls []string 36 for _, r := range controller.cfg.StandbyRemotes() { 37 // TODO: url sanitize name 38 remoteUrl := strings.Replace(r.RemoteURLTemplate(), dsess.URLTemplateDatabasePlaceholder, name, -1) 39 40 // We're going to check if this database already has 41 // the remote we're trying to add. This can happen in 42 // the DOLT_UNDROP case, for example. If a matching 43 // remote exists, we assert that it has the expected 44 // URL. It's an error otherwise. 45 remotes, err := denv.GetRemotes() 46 if err != nil { 47 // XXX: An error here means we are not replicating. 48 return err 49 } 50 51 var er env.Remote 52 var ok bool 53 if er, ok = remotes.Get(r.Name()); ok { 54 if er.Url != remoteUrl { 55 return fmt.Errorf("invalid remote (%s) for cluster replication found in database %s: expect url %s but the existing remote had url %s", r.Name(), name, remoteUrl, er.Url) 56 } 57 } else { 58 // TODO: Assert remotesapi URL. 59 er = env.NewRemote(r.Name(), remoteUrl, nil) 60 err := denv.AddRemote(er) 61 if err != nil { 62 return err 63 } 64 } 65 66 remoteDBs = append(remoteDBs, func(ctx context.Context) (*doltdb.DoltDB, error) { 67 return er.GetRemoteDB(ctx, types.Format_Default, dialprovider) 68 }) 69 remoteUrls = append(remoteUrls, remoteUrl) 70 } 71 72 // When we create a new database, we stop trying to replicate a 73 // previous drop of that database to the replicas. Successfully 74 // replicating a new head update will set the state of any 75 // existing database to the state of this new database going 76 // forward. 77 controller.cancelDropDatabaseReplication(name) 78 79 role, _ := controller.roleAndEpoch() 80 for i, r := range controller.cfg.StandbyRemotes() { 81 ttfdir, err := denv.TempTableFilesDir() 82 if err != nil { 83 // XXX: An error here means we are not replicating to every standby. 84 return err 85 } 86 commitHook := newCommitHook(controller.lgr, r.Name(), remoteUrls[i], name, role, remoteDBs[i], denv.DoltDB, ttfdir) 87 denv.DoltDB.PrependCommitHook(ctx, commitHook) 88 controller.registerCommitHook(commitHook) 89 if err := commitHook.Run(bt); err != nil { 90 // XXX: An error here means we are not replicating to every standby. 91 return err 92 } 93 } 94 95 return nil 96 } 97 }