punchcard-cms/punchcard

View on GitHub
lib/schedule/utils.js

Summary

Maintainability
B
6 hrs
Test Coverage
'use strict';

const scheduler = require('node-schedule');
const moment = require('moment-timezone');

const applications = require('../applications');
const database = require('../database');

/*
 * Set up Revision
 *
 * @param {object} revision - A full revision of a piece of content, with all fields that are saved in the database, plus its content type's name (and slug of name) and identifier's slug
 *
 * @return Promise
 */
const setup = revision => {
  // Insert revision in to schedule table
  return database('schedule').insert({
    'id': revision.id,
    'revision': revision.revision,
    'language': revision.language,
    'sunrise': revision.sunrise,
    'sunset': revision.sunset,
    'attributes': revision.value,
    'type': revision.type,
    'key': revision.identifier,
    'type-slug': revision['type-slug'],
    'key-slug': revision.slug,
  }).then(() => {
    // If revision has a sunset, update live DB with it
    if (revision.sunset) {
      return database('live').update('sunset', revision.sunset).where({
        id: revision.id,
      });
    }

    return true;
  });
};

/*
 * Pull content from live
 *
 * @param {object} revision - A full revision of a piece of content, with all fields that are saved in the database, plus its content type's name (and slug of name) and identifier's slug
 *
 * sunset webhook here
 * @return Promise
 */
const pull = (revision, apps) => {
  return database('live').select('id', 'sunset').where({
    id: revision.id,
  }).then(item => {
    const result = item[0];
    const now = moment().unix();
    const sunset = result.sunset ? moment(result.sunset).unix() : false;
    const options = {
      trigger: 'sunset',
      apps,
    };

    if (sunset && sunset <= now) {
      return database('live').where({
        id: result.id,
      }).del().then(() => {
        return applications.send(options);
      });
    }

    return false;
  });
};

/*
 * Push content live
 *
 * @param {object} revision - A full revision of a piece of content, with all fields that are saved in the database, plus its content type's name (and slug of name) and identifier's slug
 *
 * @return Promise
 */
const push = (revision, apps) => {
  const options = {
    trigger: 'updated',
    apps,
  };

  // Find revision in schedule table
  return database('schedule').select('*').where({
    id: revision.id,
    revision: revision.revision,
  }).then(item => {
    const result = item[0];
    const now = moment().unix();
    const sunrise = result.sunrise ? moment(result.sunrise).unix() : false;

    // If it's time to sunrise, do it
    if (sunrise <= now) {
      // See if the item is in the live DB already
      return database('live').select('id').where({
        id: result.id,
        language: result.language,
      }).then(items => {
        // If item not in live DB, insert it in full
        if (items.length === 0) {
          options.trigger = 'live';

          return database('live').insert(result).then(() => {
            return applications.send(options);
          });
        }

        // If item in live DB, update accordingly
        return database('live').update({
          'revision': result.revision,
          'sunrise': result.sunrise,
          'attributes': result.attributes,
          'type': result.type,
          'key': result.key,
          'type-slug': result['type-slug'],
          'key-slug': result['key-slug'],
        }).where({
          id: result.id,
          language: result.language,
        });
      }).then(() => {
        // Delete revision from schedule DB
        return database('schedule').where({
          id: result.id,
          revision: result.revision,
        }).del();
      }).then(() => {
        // notify all updated endpoints

        return applications.send(options);
      });
    }

    return true;
  });
};

/*
 * Sunrise
 *
 * @param {object} revision - A full revision of a piece of content, with all fields that are saved in the database, plus its content type's name (and slug of name) and identifier's slug
 *
 * @return Promise
 */
const sunrise = (revision, apps) => {
  const now = moment().unix();
  const live = moment(revision.sunrise).format();

  return new Promise(res => {
    if (moment(revision.sunrise).unix() <= now) {
      push(revision, apps).catch(e => {
        // Need to message out here as we can't properly reject Promises
        console.error(`Sunrise failed: ${e}`); // eslint-disable-line no-console
      });
    }
    else {
      scheduler.scheduleJob(live, () => {
        push(revision, apps).catch(e => {
          // Need to message out here as we can't properly reject Promises
          console.error(`Sunrise failed: ${e}`); // eslint-disable-line no-console
        });
      });
    }

    res(true);
  });
};

/*
 * Sunset
 *
 * @param {object} revision - A full revision of a piece of content, with all fields that are saved in the database, plus its content type's name (and slug of name) and identifier's slug
 *
 * @return Promise
 */
const sunset = (revision, apps) => {
  const now = moment().unix();
  const down = revision.sunset ? moment(revision.sunset).format() : false;

  return new Promise(res => {
    if (down) {
      if (moment(revision.sunset).unix() <= now) {
        pull(revision, apps).catch(e => {
          // Need to message out here as we can't properly reject Promises
          console.error(`Sunset failed: ${e.message}`); // eslint-disable-line no-console
        });
      }
      else {
        scheduler.scheduleJob(down, () => {
          pull(revision, apps).catch(e => {
            // Need to message out here as we can't properly reject Promises
            console.error(`Sunset failed: ${e.message}`); // eslint-disable-line no-console
          });
        });
      }
    }

    res(true);
  });
};

module.exports = {
  setup,
  pull,
  push,
  sunrise,
  sunset,
};