// getVersion gets the migration version in the database. func getVersion(tx migration.LimitedTx) (int, error) { var version int row := tx.QueryRow("SELECT version FROM migration_version") if err := row.Scan(&version); err != nil { return 0, err } return version, nil }
func (d dbVersion) get(tx migration.LimitedTx) (int, error) { var version int r := tx.QueryRow(d.GetSQL) if err := r.Scan(&version); err != nil { return 0, err } return version, nil }
func CreateEventIDSequencesForInFlightBuilds(tx migration.LimitedTx) error { cursor := 0 for { var id, eventIDStart int err := tx.QueryRow(` SELECT id, max(event_id) FROM builds LEFT JOIN build_events ON build_id = id WHERE id > $1 AND status = 'started' GROUP BY id ORDER BY id ASC LIMIT 1 `, cursor).Scan(&id, &eventIDStart) if err != nil { if err == sql.ErrNoRows { break } return err } cursor = id _, err = tx.Exec(fmt.Sprintf(` CREATE SEQUENCE %s MINVALUE 0 START WITH %d `, buildEventSeq(id), eventIDStart+1)) if err != nil { return err } } return nil }
func AddBuildEvents(tx migration.LimitedTx) error { _, err := tx.Exec(` CREATE TABLE build_events ( id serial PRIMARY KEY, build_id integer REFERENCES builds (id), type varchar(32) NOT NULL, payload text NOT NULL ) `) if err != nil { return err } cursor := 0 for { var id int var buildLog sql.NullString err := tx.QueryRow(` SELECT id, log FROM builds WHERE id > $1 ORDER BY id ASC LIMIT 1 `, cursor).Scan(&id, &buildLog) if err != nil { if err == sql.ErrNoRows { break } return err } cursor = id if !buildLog.Valid { continue } logBuf := bytes.NewBufferString(buildLog.String) decoder := json.NewDecoder(logBuf) for { var entry logEntry err := decoder.Decode(&entry) if err != nil { if err != io.EOF { // non-JSON log; assume v0.0 _, err = tx.Exec(` INSERT INTO build_events (build_id, type, payload) VALUES ($1, $2, $3) `, id, "version", "0.0") if err != nil { return err } _, err = tx.Exec(` INSERT INTO build_events (build_id, type, payload) VALUES ($1, $2, $3) `, id, "log", buildLog.String) if err != nil { return err } } break } if entry.Type != "" && entry.EventPayload != nil { _, err = tx.Exec(` INSERT INTO build_events (build_id, type, payload) VALUES ($1, $2, $3) `, id, entry.Type, []byte(*entry.EventPayload)) if err != nil { return err } continue } if entry.Version != "" { versionEnc, err := json.Marshal(entry.Version) if err != nil { return err } _, err = tx.Exec(` INSERT INTO build_events (build_id, type, payload) VALUES ($1, $2, $3) `, id, "version", versionEnc) if err != nil { return err } continue } return fmt.Errorf("malformed event stream; got stuck at %s", logBuf.String()) } } _, err = tx.Exec(` ALTER TABLE builds DROP COLUMN log `) if err != nil { return err } return nil }
func AddEngineAndEngineMetadataToBuilds(tx migration.LimitedTx) error { _, err := tx.Exec(`ALTER TABLE builds ADD COLUMN engine varchar(16)`) if err != nil { return err } _, err = tx.Exec(`ALTER TABLE builds ADD COLUMN engine_metadata text`) if err != nil { return err } cursor := 0 for { var id int var guid, endpoint string err := tx.QueryRow(` SELECT id, guid, endpoint FROM builds WHERE id > $1 AND guid != '' ORDER BY id ASC LIMIT 1 `, cursor).Scan(&id, &guid, &endpoint) if err != nil { if err == sql.ErrNoRows { break } return err } cursor = id engineMetadata := turbineMetadata{ Guid: guid, Endpoint: endpoint, } payload, err := json.Marshal(engineMetadata) if err != nil { continue } _, err = tx.Exec(` UPDATE builds SET engine = $1, engine_metadata = $2 WHERE id = $3 `, "turbine", payload, id) if err != nil { continue } } _, err = tx.Exec(`ALTER TABLE builds DROP COLUMN guid`) if err != nil { return err } _, err = tx.Exec(`ALTER TABLE builds DROP COLUMN endpoint`) if err != nil { return err } return nil }
func ReplaceBuildsAbortHijackURLsWithGuidAndEndpoint(tx migration.LimitedTx) error { _, err := tx.Exec(`ALTER TABLE builds ADD COLUMN guid varchar(36)`) if err != nil { return err } _, err = tx.Exec(`ALTER TABLE builds ADD COLUMN endpoint varchar(128)`) if err != nil { return err } cursor := 0 for { var id int var abortURLStr sql.NullString err := tx.QueryRow(` SELECT id, abort_url FROM builds WHERE id > $1 LIMIT 1 `, cursor).Scan(&id, &abortURLStr) if err != nil { if err == sql.ErrNoRows { break } return err } cursor = id if !abortURLStr.Valid { continue } // determine guid + endpoint from abort url // // format should be http://foo.com:5050/builds/some-guid/abort // // best-effort; skip if not possible, not a big deal abortURL, err := url.Parse(abortURLStr.String) if err != nil { continue } pathSegments := strings.Split(abortURL.Path, "/") if len(pathSegments) != 4 { continue } guid := pathSegments[2] endpoint := abortURL.Scheme + "://" + abortURL.Host _, err = tx.Exec(` UPDATE builds SET guid = $1, endpoint = $2 WHERE id = $3 `, guid, endpoint, id) if err != nil { continue } } _, err = tx.Exec(`ALTER TABLE builds DROP COLUMN abort_url`) if err != nil { return err } _, err = tx.Exec(`ALTER TABLE builds DROP COLUMN hijack_url`) if err != nil { return err } return nil }