Source: migrations/state.js

/**
 * migrations/state.js - migration state for hsd.
 * Copyright (c) 2021, Nodari Chkuaselidze (MIT License)
 */
'use strict';

const assert = require('bsert');
const bio = require('bufio');
const {encoding} = bio;

/**
 * State of database migrations.
 * Because migration IDs are only increasing, we only need
 * to store the last one.
 * @alias module.migrations.MigrationState
 * @property {Boolean} inProgress - is/was migration in progress
 * NOTE: If inProgress is true, we know lastMigration + 1 was the one in
 *       progress.
 * @property {Number} lastMigration - last migration
 * NOTE: Migration numbers start from 1.
 *       0 - means there is no migration.
 */

class MigrationState extends bio.Struct {
  /**
   * Create MigrationState
   * @constructor
   */

  constructor() {
    super();

    this.inProgress = false;
    this.nextMigration = 0;
    this.skipped = [];
  }

  get lastMigration() {
    return this.nextMigration - 1;
  }

  /**
   * Inject properties from another state.
   * @param {MigrationState} obj
   * @returns MigrationState;
   */

  inject(obj) {
    assert(obj instanceof MigrationState);
    this.inProgress = obj.inProgress;
    this.nextMigration = obj.nextMigration;
    this.skipped = obj.skipped.slice();
    return this;
  }

  /**
   * Get size of the encoded migration state object.
   * @returns {Number}
   */

  getSize() {
    // flags + last migration number
    let size = 4; // flags
    size += encoding.sizeVarint(this.nextMigration);
    size += encoding.sizeVarint(this.skipped.length);

    for (const id of this.skipped)
      size += encoding.sizeVarint(id);

    return size;
  }

  /**
   * Serialize migration state.
   * @param {BufferWriter} bw
   * @returns {BufferWriter}
   */

  write(bw) {
    let flags = 0;

    if (this.inProgress)
      flags |= 1 << 0;

    bw.writeU32(flags);
    bw.writeVarint(this.nextMigration);
    bw.writeVarint(this.skipped.length);

    for (const id of this.skipped)
      bw.writeVarint(id);

    return bw;
  }

  /**
   * Deserialize migration state.
   * @param {BufferReader}
   * @returns {MigrationState}
   */

  read(br) {
    const flags = br.readU32();

    this.inProgress = (flags & 1) !== 0;
    this.nextMigration = br.readVarint();
    this.skipped = [];

    const skippedItems = br.readVarint();

    for (let i = 0; i < skippedItems; i++)
      this.skipped.push(br.readVarint(0));

    return this;
  }
}

module.exports = MigrationState;