mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
Use context-bound SQL methods
Changes: Exec -> ExecContext Query -> QueryContext QueryRow -> QueryRowContext Rebind and store all possible queries before using them Closes: #276
This commit is contained in:
@@ -72,9 +72,22 @@ const (
|
|||||||
|
|
||||||
type sqlStore struct {
|
type sqlStore struct {
|
||||||
db *sqlx.DB
|
db *sqlx.DB
|
||||||
|
insertAppQuery string
|
||||||
// TODO we should prepare all of the statements, rebind them
|
updateAppQuery string
|
||||||
// and store them all here.
|
getAppQuery string
|
||||||
|
selectAppConfigQuery string
|
||||||
|
removeAppQuery string
|
||||||
|
insertRouteQuery string
|
||||||
|
updateRouteQuery string
|
||||||
|
checkRouteAppQuery string
|
||||||
|
checkRouteQuery string
|
||||||
|
getRouteQuery string
|
||||||
|
removeRouteQuery string
|
||||||
|
insertCallQuery string
|
||||||
|
getCallQuery string
|
||||||
|
insertLogQuery string
|
||||||
|
getLogQuery string
|
||||||
|
deleteLogQuery string
|
||||||
}
|
}
|
||||||
|
|
||||||
// New will open the db specified by url, create any tables necessary
|
// New will open the db specified by url, create any tables necessary
|
||||||
@@ -133,7 +146,56 @@ func New(url *url.URL) (models.Datastore, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &sqlStore{db: db}, nil
|
dstore := &sqlStore{
|
||||||
|
db: db,
|
||||||
|
insertAppQuery: db.Rebind("INSERT INTO apps (name, config) VALUES (?, ?);"),
|
||||||
|
selectAppConfigQuery: db.Rebind(`SELECT config FROM apps WHERE name=?`),
|
||||||
|
updateAppQuery: db.Rebind(`UPDATE apps SET config=? WHERE name=?`),
|
||||||
|
removeAppQuery: db.Rebind(`DELETE FROM apps WHERE name = ?`),
|
||||||
|
getAppQuery: db.Rebind(`SELECT name, config FROM apps WHERE name=?`),
|
||||||
|
checkRouteAppQuery: db.Rebind(`SELECT 1 FROM apps WHERE name=?`),
|
||||||
|
checkRouteQuery: db.Rebind(`SELECT 1 FROM routes WHERE app_name=? AND path=?`),
|
||||||
|
insertRouteQuery: db.Rebind(`INSERT INTO routes (
|
||||||
|
app_name,
|
||||||
|
path,
|
||||||
|
image,
|
||||||
|
format,
|
||||||
|
memory,
|
||||||
|
type,
|
||||||
|
timeout,
|
||||||
|
idle_timeout,
|
||||||
|
headers,
|
||||||
|
config
|
||||||
|
)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);`),
|
||||||
|
getRouteQuery: db.Rebind(fmt.Sprintf("%s WHERE app_name=? AND path=?", routeSelector)),
|
||||||
|
updateRouteQuery: db.Rebind(`UPDATE routes SET
|
||||||
|
image = ?,
|
||||||
|
format = ?,
|
||||||
|
memory = ?,
|
||||||
|
type = ?,
|
||||||
|
timeout = ?,
|
||||||
|
idle_timeout = ?,
|
||||||
|
headers = ?,
|
||||||
|
config = ?
|
||||||
|
WHERE app_name=? AND path=?;`),
|
||||||
|
removeRouteQuery: db.Rebind(`DELETE FROM routes WHERE path = ? AND app_name = ?`),
|
||||||
|
insertCallQuery: db.Rebind(`INSERT INTO calls (
|
||||||
|
id,
|
||||||
|
created_at,
|
||||||
|
started_at,
|
||||||
|
completed_at,
|
||||||
|
status,
|
||||||
|
app_name,
|
||||||
|
path
|
||||||
|
)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?);`),
|
||||||
|
getCallQuery: db.Rebind(fmt.Sprintf(`%s WHERE id=? AND app_name=?`, callSelector)),
|
||||||
|
insertLogQuery: db.Rebind(`INSERT INTO logs (id, log) VALUES (?, ?);`),
|
||||||
|
getLogQuery: db.Rebind(`SELECT log FROM logs WHERE id=?`),
|
||||||
|
deleteLogQuery: db.Rebind(`DELETE FROM logs WHERE id=?`),
|
||||||
|
}
|
||||||
|
return dstore, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ds *sqlStore) InsertApp(ctx context.Context, app *models.App) (*models.App, error) {
|
func (ds *sqlStore) InsertApp(ctx context.Context, app *models.App) (*models.App, error) {
|
||||||
@@ -146,8 +208,7 @@ func (ds *sqlStore) InsertApp(ctx context.Context, app *models.App) (*models.App
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
query := ds.db.Rebind("INSERT INTO apps (name, config) VALUES (?, ?);")
|
_, err = ds.db.ExecContext(ctx, ds.insertAppQuery, app.Name, string(cbyte))
|
||||||
_, err = ds.db.Exec(query, app.Name, string(cbyte))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch err := err.(type) {
|
switch err := err.(type) {
|
||||||
case *mysql.MySQLError:
|
case *mysql.MySQLError:
|
||||||
@@ -172,8 +233,7 @@ func (ds *sqlStore) InsertApp(ctx context.Context, app *models.App) (*models.App
|
|||||||
func (ds *sqlStore) UpdateApp(ctx context.Context, newapp *models.App) (*models.App, error) {
|
func (ds *sqlStore) UpdateApp(ctx context.Context, newapp *models.App) (*models.App, error) {
|
||||||
app := &models.App{Name: newapp.Name}
|
app := &models.App{Name: newapp.Name}
|
||||||
err := ds.Tx(func(tx *sqlx.Tx) error {
|
err := ds.Tx(func(tx *sqlx.Tx) error {
|
||||||
query := tx.Rebind(`SELECT config FROM apps WHERE name=?`)
|
row := tx.QueryRowContext(ctx, ds.selectAppConfigQuery, app.Name)
|
||||||
row := tx.QueryRow(query, app.Name)
|
|
||||||
|
|
||||||
var config string
|
var config string
|
||||||
if err := row.Scan(&config); err != nil {
|
if err := row.Scan(&config); err != nil {
|
||||||
@@ -197,8 +257,7 @@ func (ds *sqlStore) UpdateApp(ctx context.Context, newapp *models.App) (*models.
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
query = tx.Rebind(`UPDATE apps SET config=? WHERE name=?`)
|
res, err := tx.ExecContext(ctx, ds.updateAppQuery, string(cbyte), app.Name)
|
||||||
res, err := tx.Exec(query, string(cbyte), app.Name)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -220,14 +279,12 @@ func (ds *sqlStore) UpdateApp(ctx context.Context, newapp *models.App) (*models.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ds *sqlStore) RemoveApp(ctx context.Context, appName string) error {
|
func (ds *sqlStore) RemoveApp(ctx context.Context, appName string) error {
|
||||||
query := ds.db.Rebind(`DELETE FROM apps WHERE name = ?`)
|
_, err := ds.db.ExecContext(ctx, ds.removeAppQuery, appName)
|
||||||
_, err := ds.db.Exec(query, appName)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ds *sqlStore) GetApp(ctx context.Context, name string) (*models.App, error) {
|
func (ds *sqlStore) GetApp(ctx context.Context, name string) (*models.App, error) {
|
||||||
query := ds.db.Rebind(`SELECT name, config FROM apps WHERE name=?`)
|
row := ds.db.QueryRowContext(ctx, ds.getAppQuery, name)
|
||||||
row := ds.db.QueryRow(query, name)
|
|
||||||
|
|
||||||
var resName, config string
|
var resName, config string
|
||||||
err := row.Scan(&resName, &config)
|
err := row.Scan(&resName, &config)
|
||||||
@@ -257,7 +314,7 @@ func (ds *sqlStore) GetApps(ctx context.Context, filter *models.AppFilter) ([]*m
|
|||||||
res := []*models.App{}
|
res := []*models.App{}
|
||||||
query, args := buildFilterAppQuery(filter)
|
query, args := buildFilterAppQuery(filter)
|
||||||
query = ds.db.Rebind(fmt.Sprintf("SELECT DISTINCT name, config FROM apps %s", query))
|
query = ds.db.Rebind(fmt.Sprintf("SELECT DISTINCT name, config FROM apps %s", query))
|
||||||
rows, err := ds.db.Query(query, args...)
|
rows, err := ds.db.QueryContext(ctx, query, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -294,15 +351,13 @@ func (ds *sqlStore) InsertRoute(ctx context.Context, route *models.Route) (*mode
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = ds.Tx(func(tx *sqlx.Tx) error {
|
err = ds.Tx(func(tx *sqlx.Tx) error {
|
||||||
query := tx.Rebind(`SELECT 1 FROM apps WHERE name=?`)
|
r := tx.QueryRowContext(ctx, ds.checkRouteAppQuery, route.AppName)
|
||||||
r := tx.QueryRow(query, route.AppName)
|
|
||||||
if err := r.Scan(new(int)); err != nil {
|
if err := r.Scan(new(int)); err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return models.ErrAppsNotFound
|
return models.ErrAppsNotFound
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
query = tx.Rebind(`SELECT 1 FROM routes WHERE app_name=? AND path=?`)
|
same, err := tx.QueryContext(ctx, ds.checkRouteQuery, route.AppName, route.Path)
|
||||||
same, err := tx.Query(query, route.AppName, route.Path)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -311,21 +366,7 @@ func (ds *sqlStore) InsertRoute(ctx context.Context, route *models.Route) (*mode
|
|||||||
return models.ErrRoutesAlreadyExists
|
return models.ErrRoutesAlreadyExists
|
||||||
}
|
}
|
||||||
|
|
||||||
query = tx.Rebind(`INSERT INTO routes (
|
_, err = tx.ExecContext(ctx, ds.insertRouteQuery,
|
||||||
app_name,
|
|
||||||
path,
|
|
||||||
image,
|
|
||||||
format,
|
|
||||||
memory,
|
|
||||||
type,
|
|
||||||
timeout,
|
|
||||||
idle_timeout,
|
|
||||||
headers,
|
|
||||||
config
|
|
||||||
)
|
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);`)
|
|
||||||
|
|
||||||
_, err = tx.Exec(query,
|
|
||||||
route.AppName,
|
route.AppName,
|
||||||
route.Path,
|
route.Path,
|
||||||
route.Image,
|
route.Image,
|
||||||
@@ -347,8 +388,7 @@ func (ds *sqlStore) InsertRoute(ctx context.Context, route *models.Route) (*mode
|
|||||||
func (ds *sqlStore) UpdateRoute(ctx context.Context, newroute *models.Route) (*models.Route, error) {
|
func (ds *sqlStore) UpdateRoute(ctx context.Context, newroute *models.Route) (*models.Route, error) {
|
||||||
var route models.Route
|
var route models.Route
|
||||||
err := ds.Tx(func(tx *sqlx.Tx) error {
|
err := ds.Tx(func(tx *sqlx.Tx) error {
|
||||||
query := tx.Rebind(fmt.Sprintf("%s WHERE app_name=? AND path=?", routeSelector))
|
row := tx.QueryRowContext(ctx, ds.getRouteQuery, newroute.AppName, newroute.Path)
|
||||||
row := tx.QueryRow(query, newroute.AppName, newroute.Path)
|
|
||||||
if err := scanRoute(row, &route); err == sql.ErrNoRows {
|
if err := scanRoute(row, &route); err == sql.ErrNoRows {
|
||||||
return models.ErrRoutesNotFound
|
return models.ErrRoutesNotFound
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
@@ -367,18 +407,7 @@ func (ds *sqlStore) UpdateRoute(ctx context.Context, newroute *models.Route) (*m
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
query = tx.Rebind(`UPDATE routes SET
|
res, err := tx.ExecContext(ctx, ds.updateAppQuery,
|
||||||
image = ?,
|
|
||||||
format = ?,
|
|
||||||
memory = ?,
|
|
||||||
type = ?,
|
|
||||||
timeout = ?,
|
|
||||||
idle_timeout = ?,
|
|
||||||
headers = ?,
|
|
||||||
config = ?
|
|
||||||
WHERE app_name=? AND path=?;`)
|
|
||||||
|
|
||||||
res, err := tx.Exec(query,
|
|
||||||
route.Image,
|
route.Image,
|
||||||
route.Format,
|
route.Format,
|
||||||
route.Memory,
|
route.Memory,
|
||||||
@@ -412,8 +441,7 @@ func (ds *sqlStore) UpdateRoute(ctx context.Context, newroute *models.Route) (*m
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ds *sqlStore) RemoveRoute(ctx context.Context, appName, routePath string) error {
|
func (ds *sqlStore) RemoveRoute(ctx context.Context, appName, routePath string) error {
|
||||||
query := ds.db.Rebind(`DELETE FROM routes WHERE path = ? AND app_name = ?`)
|
res, err := ds.db.ExecContext(ctx, ds.removeRouteQuery, routePath, appName)
|
||||||
res, err := ds.db.Exec(query, routePath, appName)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -431,9 +459,7 @@ func (ds *sqlStore) RemoveRoute(ctx context.Context, appName, routePath string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ds *sqlStore) GetRoute(ctx context.Context, appName, routePath string) (*models.Route, error) {
|
func (ds *sqlStore) GetRoute(ctx context.Context, appName, routePath string) (*models.Route, error) {
|
||||||
rSelectCondition := "%s WHERE app_name=? AND path=?"
|
row := ds.db.QueryRowContext(ctx, ds.getRouteQuery, appName, routePath)
|
||||||
query := ds.db.Rebind(fmt.Sprintf(rSelectCondition, routeSelector))
|
|
||||||
row := ds.db.QueryRow(query, appName, routePath)
|
|
||||||
|
|
||||||
var route models.Route
|
var route models.Route
|
||||||
err := scanRoute(row, &route)
|
err := scanRoute(row, &route)
|
||||||
@@ -449,9 +475,8 @@ func (ds *sqlStore) GetRoute(ctx context.Context, appName, routePath string) (*m
|
|||||||
func (ds *sqlStore) GetRoutes(ctx context.Context, filter *models.RouteFilter) ([]*models.Route, error) {
|
func (ds *sqlStore) GetRoutes(ctx context.Context, filter *models.RouteFilter) ([]*models.Route, error) {
|
||||||
res := []*models.Route{}
|
res := []*models.Route{}
|
||||||
query, args := buildFilterRouteQuery(filter)
|
query, args := buildFilterRouteQuery(filter)
|
||||||
query = fmt.Sprintf("%s %s", routeSelector, query)
|
query = ds.db.Rebind(fmt.Sprintf("%s %s", routeSelector, query))
|
||||||
query = ds.db.Rebind(query)
|
rows, err := ds.db.QueryContext(ctx, query, args...)
|
||||||
rows, err := ds.db.Query(query, args...)
|
|
||||||
// todo: check for no rows so we don't respond with a sql 500 err
|
// todo: check for no rows so we don't respond with a sql 500 err
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -490,7 +515,7 @@ func (ds *sqlStore) GetRoutesByApp(ctx context.Context, appName string, filter *
|
|||||||
|
|
||||||
query := fmt.Sprintf("%s %s", routeSelector, filterQuery)
|
query := fmt.Sprintf("%s %s", routeSelector, filterQuery)
|
||||||
query = ds.db.Rebind(query)
|
query = ds.db.Rebind(query)
|
||||||
rows, err := ds.db.Query(query, args...)
|
rows, err := ds.db.QueryContext(ctx, query, args...)
|
||||||
// todo: check for no rows so we don't respond with a sql 500 err
|
// todo: check for no rows so we don't respond with a sql 500 err
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -527,18 +552,7 @@ func (ds *sqlStore) Tx(f func(*sqlx.Tx) error) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ds *sqlStore) InsertCall(ctx context.Context, call *models.Call) error {
|
func (ds *sqlStore) InsertCall(ctx context.Context, call *models.Call) error {
|
||||||
query := ds.db.Rebind(`INSERT INTO calls (
|
_, err := ds.db.ExecContext(ctx, ds.insertCallQuery, call.ID, call.CreatedAt.String(),
|
||||||
id,
|
|
||||||
created_at,
|
|
||||||
started_at,
|
|
||||||
completed_at,
|
|
||||||
status,
|
|
||||||
app_name,
|
|
||||||
path
|
|
||||||
)
|
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?);`)
|
|
||||||
|
|
||||||
_, err := ds.db.Exec(query, call.ID, call.CreatedAt.String(),
|
|
||||||
call.StartedAt.String(), call.CompletedAt.String(),
|
call.StartedAt.String(), call.CompletedAt.String(),
|
||||||
call.Status, call.AppName, call.Path)
|
call.Status, call.AppName, call.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -552,9 +566,7 @@ func (ds *sqlStore) InsertCall(ctx context.Context, call *models.Call) error {
|
|||||||
// if we store the whole thing then it adds a lot of disk space and then we can
|
// if we store the whole thing then it adds a lot of disk space and then we can
|
||||||
// make async only queue hints instead of entire calls (mq a lot smaller space wise). pick.
|
// make async only queue hints instead of entire calls (mq a lot smaller space wise). pick.
|
||||||
func (ds *sqlStore) GetCall(ctx context.Context, appName, callID string) (*models.Call, error) {
|
func (ds *sqlStore) GetCall(ctx context.Context, appName, callID string) (*models.Call, error) {
|
||||||
query := fmt.Sprintf(`%s WHERE id=? AND app_name=?`, callSelector)
|
row := ds.db.QueryRowContext(ctx, ds.getCallQuery, callID, appName)
|
||||||
query = ds.db.Rebind(query)
|
|
||||||
row := ds.db.QueryRow(query, callID, appName)
|
|
||||||
|
|
||||||
var call models.Call
|
var call models.Call
|
||||||
err := scanCall(row, &call)
|
err := scanCall(row, &call)
|
||||||
@@ -569,7 +581,7 @@ func (ds *sqlStore) GetCalls(ctx context.Context, filter *models.CallFilter) ([]
|
|||||||
query, args := buildFilterCallQuery(filter)
|
query, args := buildFilterCallQuery(filter)
|
||||||
query = fmt.Sprintf("%s %s", callSelector, query)
|
query = fmt.Sprintf("%s %s", callSelector, query)
|
||||||
query = ds.db.Rebind(query)
|
query = ds.db.Rebind(query)
|
||||||
rows, err := ds.db.Query(query, args...)
|
rows, err := ds.db.QueryContext(ctx, query, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -590,14 +602,12 @@ func (ds *sqlStore) GetCalls(ctx context.Context, filter *models.CallFilter) ([]
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ds *sqlStore) InsertLog(ctx context.Context, callID, callLog string) error {
|
func (ds *sqlStore) InsertLog(ctx context.Context, callID, callLog string) error {
|
||||||
query := ds.db.Rebind(`INSERT INTO logs (id, log) VALUES (?, ?);`)
|
_, err := ds.db.ExecContext(ctx, ds.insertLogQuery, callID, callLog)
|
||||||
_, err := ds.db.Exec(query, callID, callLog)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ds *sqlStore) GetLog(ctx context.Context, callID string) (*models.CallLog, error) {
|
func (ds *sqlStore) GetLog(ctx context.Context, callID string) (*models.CallLog, error) {
|
||||||
query := ds.db.Rebind(`SELECT log FROM logs WHERE id=?`)
|
row := ds.db.QueryRowContext(ctx, ds.getLogQuery, callID)
|
||||||
row := ds.db.QueryRow(query, callID)
|
|
||||||
|
|
||||||
var log string
|
var log string
|
||||||
err := row.Scan(&log)
|
err := row.Scan(&log)
|
||||||
@@ -615,8 +625,7 @@ func (ds *sqlStore) GetLog(ctx context.Context, callID string) (*models.CallLog,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ds *sqlStore) DeleteLog(ctx context.Context, callID string) error {
|
func (ds *sqlStore) DeleteLog(ctx context.Context, callID string) error {
|
||||||
query := ds.db.Rebind(`DELETE FROM logs WHERE id=?`)
|
_, err := ds.db.ExecContext(ctx, ds.deleteLogQuery, callID)
|
||||||
_, err := ds.db.Exec(query, callID)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user