diff --git a/backend/controller/sql/testdata/go/mysql/types.ftl.go b/backend/controller/sql/testdata/go/mysql/types.ftl.go index 2df22e95f4..b5a44ca097 100644 --- a/backend/controller/sql/testdata/go/mysql/types.ftl.go +++ b/backend/controller/sql/testdata/go/mysql/types.ftl.go @@ -9,12 +9,18 @@ import ( type InsertClient func(context.Context, InsertRequest) (InsertResponse, error) +type QueryClient func(context.Context) (map[string]string, error) + func init() { reflection.Register( - reflection.Database[MyDbConfig](server.InitPostgres), + reflection.Database[MyDbConfig]("testdb", server.InitMySQL), reflection.ProvideResourcesForVerb( Insert, - server.PostgresDatabaseHandle[MyDbConfig](), + server.DatabaseHandle[MyDbConfig]("mysql"), + ), + reflection.ProvideResourcesForVerb( + Query, + server.DatabaseHandle[MyDbConfig]("mysql"), ), ) } diff --git a/backend/provisioner/dev_provisioner.go b/backend/provisioner/dev_provisioner.go index 04c96220b2..806708c3be 100644 --- a/backend/provisioner/dev_provisioner.go +++ b/backend/provisioner/dev_provisioner.go @@ -3,6 +3,7 @@ package provisioner import ( "context" "fmt" + "time" "github.com/XSAM/otelsql" _ "github.com/go-sql-driver/mysql" @@ -38,39 +39,61 @@ func provisionMysql(mysqlPort int) InMemResourceProvisionerFn { if err != nil { return nil, fmt.Errorf("failed to wait for mysql to be ready: %w", err) } - conn, err := otelsql.Open("mysql", mysqlDSN) - if err != nil { - return nil, fmt.Errorf("failed to connect to mysql: %w", err) - } - defer conn.Close() - - res, err := conn.Query("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = ?", dbName) - if err != nil { - return nil, fmt.Errorf("failed to query database: %w", err) - } - defer res.Close() - if res.Next() { - _, err = conn.ExecContext(ctx, "DROP DATABASE "+dbName) - if err != nil { - return nil, fmt.Errorf("failed to drop database: %w", err) + timeout := time.After(10 * time.Second) + retry := time.NewTicker(100 * time.Millisecond) + defer retry.Stop() + for { + select { + case <-timeout: + return nil, fmt.Errorf("failed to query database: %w", err) + case <-retry.C: + var ret *provisioner.Resource + ret, err = establishMySQLDB(ctx, rc, mysqlDSN, dbName, mysql, mysqlPort) + if err != nil { + logger.Debugf("failed to establish mysql database: %s", err.Error()) + continue + } + return ret, nil } + } - _, err = conn.ExecContext(ctx, "CREATE DATABASE "+dbName) + } +} + +func establishMySQLDB(ctx context.Context, rc *provisioner.ResourceContext, mysqlDSN string, dbName string, mysql *provisioner.Resource_Mysql, mysqlPort int) (*provisioner.Resource, error) { + conn, err := otelsql.Open("mysql", mysqlDSN) + if err != nil { + return nil, fmt.Errorf("failed to connect to mysql: %w", err) + } + defer conn.Close() + + res, err := conn.Query("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = ?", dbName) + if err != nil { + return nil, fmt.Errorf("failed to query database: %w", err) + } + defer res.Close() + if res.Next() { + _, err = conn.ExecContext(ctx, "DROP DATABASE "+dbName) if err != nil { - return nil, fmt.Errorf("failed to create database: %w", err) + return nil, fmt.Errorf("failed to drop database: %w", err) } + } - if mysql.Mysql == nil { - mysql.Mysql = &provisioner.MysqlResource{} - } - dsn := dsn.MySQLDSN(dbName, dsn.Port(mysqlPort)) - mysql.Mysql.Output = &provisioner.MysqlResource_MysqlResourceOutput{ - WriteDsn: dsn, - ReadDsn: dsn, - } - return rc.Resource, nil + _, err = conn.ExecContext(ctx, "CREATE DATABASE "+dbName) + if err != nil { + return nil, fmt.Errorf("failed to create database: %w", err) + } + + if mysql.Mysql == nil { + mysql.Mysql = &provisioner.MysqlResource{} + } + dsn := dsn.MySQLDSN(dbName, dsn.Port(mysqlPort)) + mysql.Mysql.Output = &provisioner.MysqlResource_MysqlResourceOutput{ + WriteDsn: dsn, + ReadDsn: dsn, } + return rc.Resource, nil } func provisionPostgres(postgresPort int) func(ctx context.Context, rc *provisioner.ResourceContext, module string, id string) (*provisioner.Resource, error) { diff --git a/docker-compose.yml b/docker-compose.yml index 9c4955de5f..4391db70cd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,6 +19,8 @@ services: retries: 60 start_period: 80s mysql: + profiles: + - mysql image: mysql:8.4.3 environment: MYSQL_ROOT_PASSWORD: secret diff --git a/jvm-runtime/ftl-runtime/common/runtime/src/main/java/xyz/block/ftl/runtime/FTLController.java b/jvm-runtime/ftl-runtime/common/runtime/src/main/java/xyz/block/ftl/runtime/FTLController.java index c1c77e8833..f51ca8d98e 100644 --- a/jvm-runtime/ftl-runtime/common/runtime/src/main/java/xyz/block/ftl/runtime/FTLController.java +++ b/jvm-runtime/ftl-runtime/common/runtime/src/main/java/xyz/block/ftl/runtime/FTLController.java @@ -88,10 +88,8 @@ public byte[] getConfig(String secretName) { } public Datasource getDatasource(String name) { - log.errorf("GET DATASOURCE"); List databasesList = getModuleContext().getDatabasesList(); for (var i : databasesList) { - log.errorf("DSN %s %s", i.getName(), i.getDsn()); if (i.getName().equals(name)) { return Datasource.fromDSN(i.getDsn(), i.getType()); }