~evanj/cms

da13ad09881f7f92ed44c54cf4cd809f3b31ee57 — Evan J 2 months ago 9d2dfb0
Feat(db): Removed non transactions and deadlocks from db layer.
4 files changed, 59 insertions(+), 22 deletions(-)

M TODO
M internal/s/db/action.go
M internal/s/db/db.go
M internal/s/db/user.go
M TODO => TODO +1 -3
@@ 1,9 1,7 @@
[high]
db.SetMaxOpenConns(1): test for deadlocks in DB code (remove all db.Query and 
  db.Exec in favor of t.Query and t.Exec)
Testing: 100% happy path and 80% total
Documentation
Doc pages: Contact, FAQ, Terms, Privacy, Tour
Pages: Doc, Contact, FAQ, Terms, Privacy, Tour
Depth option on APIs
When editing existing references don't blow away prev inputs
Forgot password

M internal/s/db/action.go => internal/s/db/action.go +15 -1
@@ 8,7 8,21 @@ import (
)

func (db *DB) ActionNew(o org.Org, at time.Time) error {
	_, err := db.Exec("INSERT INTO cms_action (ORG_ID, AT) VALUES (?, ?)", o.ID(), at.Format("2006-01-02 03:04:05"))
	t, err := db.Begin()
	if err != nil {
		return err
	}
	defer t.Rollback()

	if err := db.actionNew(t, o, at); err != nil {
		return err
	}

	return t.Commit()
}

func (db *DB) actionNew(t *sql.Tx, o org.Org, at time.Time) error {
	_, err := t.Exec("INSERT INTO cms_action (ORG_ID, AT) VALUES (?, ?)", o.ID(), at.Format("2006-01-02 03:04:05"))
	return err
}


M internal/s/db/db.go => internal/s/db/db.go +26 -16
@@ 121,12 121,18 @@ func (db *DB) migrate() error {
		_   interface{}
	)

	t, err := db.Begin()
	if err != nil {
		return err
	}
	defer t.Rollback()

	for _, migrationSet := range newMigrationSlice(migrations) {
		key := migrationSet[0]
		m := migrationSet[1]

		var count int
		if err := db.QueryRow("SELECT COUNT(*) FROM cms_migrate WHERE NAME=?", key).Scan(&count); err != nil {
		if err := t.QueryRow("SELECT COUNT(*) FROM cms_migrate WHERE NAME=?", key).Scan(&count); err != nil {
			// Catch first error of DB setup.
			if !strings.Contains(err.Error(), "cms_migrate' doesn't exist") {
				return err


@@ 137,12 143,6 @@ func (db *DB) migrate() error {
			continue
		}

		t, err := db.Begin()
		if err != nil {
			return err
		}
		defer t.Rollback()

		for _, q := range strings.Split(m, ";") {
			q = strings.TrimSpace(q)
			if q == "" {


@@ 153,11 153,7 @@ func (db *DB) migrate() error {
			}
		}

		if err := t.Commit(); err != nil {
			return err
		}

		if _, err := db.Exec("INSERT INTO cms_migrate (NAME) VALUES (?)", key); err != nil {
		if _, err := t.Exec("INSERT INTO cms_migrate (NAME) VALUES (?)", key); err != nil {
			return err
		}
	}


@@ 175,7 171,7 @@ func (db *DB) migrate() error {

	for _, vt := range vtypes {
		var count int
		if err := db.QueryRow("SELECT COUNT(*) FROM cms_valuetype WHERE VALUE=?", vt).Scan(&count); err != nil {
		if err := t.QueryRow("SELECT COUNT(*) FROM cms_valuetype WHERE VALUE=?", vt).Scan(&count); err != nil {
			return err
		}



@@ 183,17 179,31 @@ func (db *DB) migrate() error {
			continue
		}

		if _, err = db.Exec(`INSERT INTO cms_valuetype (VALUE) values (?);`, vt); err != nil {
		if _, err = t.Exec(`INSERT INTO cms_valuetype (VALUE) values (?);`, vt); err != nil {
			return err
		}
	}

	return nil
	return t.Commit()
}

// FileExists makes sure SOME space and content owns the file. I.E. deleted
// spaces can't server files.
func (db *DB) FileExists(URL string) (bool, error) {
	t, err := db.Begin()
	if err != nil {
		return false, err
	}

	ok, err := db.fileExists(t, URL)
	if err != nil {
		return false, err
	}

	return ok, t.Commit()
}

func (db *DB) fileExists(t *sql.Tx, URL string) (bool, error) {
	q := `
		SELECT cms_space.ID FROM cms_value_string_small 
		JOIN cms_value ON cms_value.VALUE_ID = cms_value_string_small.ID


@@ 206,7 216,7 @@ func (db *DB) FileExists(URL string) (bool, error) {
	`

	var spaceID string
	if err := db.QueryRow(q, valuetype.File, URL).Scan(&spaceID); err != nil {
	if err := t.QueryRow(q, valuetype.File, URL).Scan(&spaceID); err != nil {
		return false, err
	}


M internal/s/db/user.go => internal/s/db/user.go +17 -2
@@ 183,11 183,26 @@ func (db *DB) userGetFromToken(t *sql.Tx, token string) (user.User, error) {
}

func (db *DB) UserSetEmail(u user.User, email string) (user.User, error) {
	t, err := db.Begin()
	if err != nil {
		return nil, err
	}
	defer t.Rollback()

	user, err := db.userSetEmail(t, u, email)
	if err != nil {
		return nil, err
	}

	return user, t.Commit()
}

func (db *DB) userSetEmail(t *sql.Tx, u user.User, email string) (user.User, error) {
	q := "INSERT INTO cms_email (EMAIL, USER_ID) VALUES (?, ?)"
	if _, err := db.Exec(q, email, u.ID()); err != nil {
	if _, err := t.Exec(q, email, u.ID()); err != nil {
		return nil, err
	}
	return db.UserGetFromToken(u.Token())
	return db.userGetFromToken(t, u.Token())
}

func (db *DB) UserSetPassword(u user.User, current, password, verifyPassword string) (user.User, error) {