Init ensures the database is at the correct version and performs any needed migrations.
(ctx context.Context)
| 154 | // Init ensures the database is at the correct version |
| 155 | // and performs any needed migrations. |
| 156 | func (m *DB) Init(ctx context.Context) error { |
| 157 | // errSkip is used when no migration or version needs to be written |
| 158 | // to the database and the transaction can be immediately rolled |
| 159 | // back rather than performing a much slower and unnecessary commit. |
| 160 | var errSkip = errors.New("skip update") |
| 161 | |
| 162 | err := m.db.Update(func(tx *bolt.Tx) error { |
| 163 | var ( |
| 164 | // current schema and version |
| 165 | schema = "v0" |
| 166 | version = 0 |
| 167 | ) |
| 168 | |
| 169 | // i represents the index of the first migration |
| 170 | // which must be run to get the database up to date. |
| 171 | // The migration's version will be checked in reverse |
| 172 | // order, decrementing i for each migration which |
| 173 | // represents a version newer than the current |
| 174 | // database version |
| 175 | i := len(migrations) |
| 176 | |
| 177 | for ; i > 0; i-- { |
| 178 | migration := migrations[i-1] |
| 179 | |
| 180 | bkt := tx.Bucket([]byte(migration.schema)) |
| 181 | if bkt == nil { |
| 182 | // Hasn't encountered another schema, go to next migration |
| 183 | if schema == "v0" { |
| 184 | continue |
| 185 | } |
| 186 | break |
| 187 | } |
| 188 | if schema == "v0" { |
| 189 | schema = migration.schema |
| 190 | vb := bkt.Get(bucketKeyDBVersion) |
| 191 | if vb != nil { |
| 192 | v, _ := binary.Varint(vb) |
| 193 | version = int(v) |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | if version >= migration.version { |
| 198 | break |
| 199 | } |
| 200 | } |
| 201 | |
| 202 | // Previous version of database found |
| 203 | if schema != "v0" { |
| 204 | updates := migrations[i:] |
| 205 | |
| 206 | // No migration updates, return immediately |
| 207 | if len(updates) == 0 { |
| 208 | return errSkip |
| 209 | } |
| 210 | |
| 211 | for _, m := range updates { |
| 212 | t0 := time.Now() |
| 213 | if err := m.migrate(tx); err != nil { |