songs.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. 'use strict';
  2. const cache = require('./cache');
  3. const db = require('./db');
  4. const io = require('./io');
  5. const utils = require('./utils');
  6. const async = require('async');
  7. const mongoose = require('mongoose');
  8. let initialized = false;
  9. let lockdown = false;
  10. module.exports = {
  11. /**
  12. * Initializes the songs module, and exits if it is unsuccessful
  13. *
  14. * @param {Function} cb - gets called once we're done initializing
  15. */
  16. init: cb => {
  17. async.waterfall([
  18. (next) => {
  19. cache.hgetall('songs', next);
  20. },
  21. (songs, next) => {
  22. if (!songs) return next();
  23. let songIds = Object.keys(songs);
  24. async.each(songIds, (songId, next) => {
  25. db.models.song.findOne({songId}, (err, song) => {
  26. if (err) next(err);
  27. else if (!song) cache.hdel('songs', songId, next);
  28. else next();
  29. });
  30. }, next);
  31. },
  32. (next) => {
  33. db.models.song.find({}, next);
  34. },
  35. (songs, next) => {
  36. async.each(songs, (song, next) => {
  37. cache.hset('songs', song.songId, cache.schemas.song(song), next);
  38. }, next);
  39. }
  40. ], (err) => {
  41. if (lockdown) return this._lockdown();
  42. if (err) {
  43. err = utils.getError(err);
  44. cb(err);
  45. } else {
  46. initialized = true;
  47. cb();
  48. }
  49. });
  50. },
  51. /**
  52. * Gets a song by id from the cache or Mongo, and if it isn't in the cache yet, adds it the cache
  53. *
  54. * @param {String} id - the id of the song we are trying to get
  55. * @param {Function} cb - gets called once we're done initializing
  56. */
  57. getSong: function(id, cb) {
  58. if (lockdown) return cb('Lockdown');
  59. async.waterfall([
  60. (next) => {
  61. if (!mongoose.Types.ObjectId.isValid(id)) return next('Id is not a valid ObjectId.');
  62. cache.hget('songs', id, next);
  63. },
  64. (song, next) => {
  65. if (song) return next(true, song);
  66. db.models.song.findOne({_id: id}, next);
  67. },
  68. (song, next) => {
  69. if (song) {
  70. cache.hset('songs', id, song, next);
  71. } else next('Song not found.');
  72. },
  73. ], (err, song) => {
  74. if (err && err !== true) return cb(err);
  75. cb(null, song);
  76. });
  77. },
  78. /**
  79. * Gets a song by song id from the cache or Mongo, and if it isn't in the cache yet, adds it the cache
  80. *
  81. * @param {String} songId - the mongo id of the song we are trying to get
  82. * @param {Function} cb - gets called once we're done initializing
  83. */
  84. getSongFromId: function(songId, cb) {
  85. if (lockdown) return cb('Lockdown');
  86. async.waterfall([
  87. (next) => {
  88. db.models.song.findOne({ songId }, next);
  89. }
  90. ], (err, song) => {
  91. if (err && err !== true) return cb(err);
  92. else return cb(null, song);
  93. });
  94. },
  95. /**
  96. * Gets a song from id from Mongo and updates the cache with it
  97. *
  98. * @param {String} songId - the id of the song we are trying to update
  99. * @param {Function} cb - gets called when an error occurred or when the operation was successful
  100. */
  101. updateSong: (songId, cb) => {
  102. if (lockdown) return cb('Lockdown');
  103. async.waterfall([
  104. (next) => {
  105. db.models.song.findOne({_id: songId}, next);
  106. },
  107. (song, next) => {
  108. if (!song) {
  109. cache.hdel('songs', songId);
  110. return next('Song not found.');
  111. }
  112. cache.hset('songs', songId, song, next);
  113. }
  114. ], (err, song) => {
  115. if (err && err !== true) return cb(err);
  116. cb(null, song);
  117. });
  118. },
  119. /**
  120. * Deletes song from id from Mongo and cache
  121. *
  122. * @param {String} songId - the id of the song we are trying to delete
  123. * @param {Function} cb - gets called when an error occurred or when the operation was successful
  124. */
  125. deleteSong: (songId, cb) => {
  126. if (lockdown) return cb('Lockdown');
  127. async.waterfall([
  128. (next) => {
  129. db.models.song.deleteOne({ songId }, next);
  130. },
  131. (next) => {
  132. cache.hdel('songs', songId, next);
  133. }
  134. ], (err) => {
  135. if (err && err !== true) cb(err);
  136. cb(null);
  137. });
  138. },
  139. _lockdown: () => {
  140. lockdown = true;
  141. }
  142. };