示例#1
0
// 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
}
示例#2
0
文件: db.go 项目: ndlib/bendo
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
}
示例#4
0
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
}