songs.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. import async from "async";
  2. import mongoose from "mongoose";
  3. import CoreClass from "../core";
  4. let SongsModule;
  5. let CacheModule;
  6. let DBModule;
  7. let UtilsModule;
  8. class _SongsModule extends CoreClass {
  9. // eslint-disable-next-line require-jsdoc
  10. constructor() {
  11. super("songs");
  12. SongsModule = this;
  13. }
  14. /**
  15. * Initialises the songs module
  16. *
  17. * @returns {Promise} - returns promise (reject, resolve)
  18. */
  19. async initialize() {
  20. this.setStage(1);
  21. CacheModule = this.moduleManager.modules.cache;
  22. DBModule = this.moduleManager.modules.db;
  23. UtilsModule = this.moduleManager.modules.utils;
  24. this.songModel = await DBModule.runJob("GET_MODEL", { modelName: "song" });
  25. this.songSchemaCache = await CacheModule.runJob("GET_SCHEMA", { schemaName: "song" });
  26. this.setStage(2);
  27. return new Promise((resolve, reject) =>
  28. async.waterfall(
  29. [
  30. next => {
  31. this.setStage(2);
  32. CacheModule.runJob("HGETALL", { table: "songs" })
  33. .then(songs => {
  34. next(null, songs);
  35. })
  36. .catch(next);
  37. },
  38. (songs, next) => {
  39. this.setStage(3);
  40. if (!songs) return next();
  41. const songIds = Object.keys(songs);
  42. return async.each(
  43. songIds,
  44. (songId, next) => {
  45. SongsModule.songModel.findOne({ songId }, (err, song) => {
  46. if (err) next(err);
  47. else if (!song)
  48. CacheModule.runJob("HDEL", {
  49. table: "songs",
  50. key: songId
  51. })
  52. .then(() => next())
  53. .catch(next);
  54. else next();
  55. });
  56. },
  57. next
  58. );
  59. },
  60. next => {
  61. this.setStage(4);
  62. SongsModule.songModel.find({}, next);
  63. },
  64. (songs, next) => {
  65. this.setStage(5);
  66. async.each(
  67. songs,
  68. (song, next) => {
  69. CacheModule.runJob("HSET", {
  70. table: "songs",
  71. key: song.songId,
  72. value: SongsModule.songSchemaCache(song)
  73. })
  74. .then(() => next())
  75. .catch(next);
  76. },
  77. next
  78. );
  79. }
  80. ],
  81. async err => {
  82. if (err) {
  83. err = await UtilsModule.runJob("GET_ERROR", { error: err });
  84. reject(new Error(err));
  85. } else resolve();
  86. }
  87. )
  88. );
  89. }
  90. /**
  91. * Gets a song by id from the cache or Mongo, and if it isn't in the cache yet, adds it the cache
  92. *
  93. * @param {object} payload - object containing the payload
  94. * @param {string} payload.id - the id of the song we are trying to get
  95. * @returns {Promise} - returns a promise (resolve, reject)
  96. */
  97. GET_SONG(payload) {
  98. return new Promise((resolve, reject) =>
  99. async.waterfall(
  100. [
  101. next => {
  102. if (!mongoose.Types.ObjectId.isValid(payload.id)) return next("Id is not a valid ObjectId.");
  103. return CacheModule.runJob("HGET", { table: "songs", key: payload.id }, this)
  104. .then(song => {
  105. next(null, song);
  106. })
  107. .catch(next);
  108. },
  109. (song, next) => {
  110. if (song) return next(true, song);
  111. return SongsModule.songModel.findOne({ _id: payload.id }, next);
  112. },
  113. (song, next) => {
  114. if (song) {
  115. CacheModule.runJob(
  116. "HSET",
  117. {
  118. table: "songs",
  119. key: payload.id,
  120. value: song
  121. },
  122. this
  123. ).then(song => next(null, song));
  124. } else next("Song not found.");
  125. }
  126. ],
  127. (err, song) => {
  128. if (err && err !== true) return reject(new Error(err));
  129. return resolve({ song });
  130. }
  131. )
  132. );
  133. }
  134. /**
  135. * Gets a song by song id from the cache or Mongo, and if it isn't in the cache yet, adds it the cache
  136. *
  137. * @param {object} payload - an object containing the payload
  138. * @param {string} payload.songId - the mongo id of the song we are trying to get
  139. * @returns {Promise} - returns a promise (resolve, reject)
  140. */
  141. GET_SONG_FROM_ID(payload) {
  142. return new Promise((resolve, reject) =>
  143. async.waterfall(
  144. [
  145. next => {
  146. SongsModule.songModel.findOne({ songId: payload.songId }, next);
  147. }
  148. ],
  149. (err, song) => {
  150. if (err && err !== true) return reject(new Error(err));
  151. return resolve({ song });
  152. }
  153. )
  154. );
  155. }
  156. /**
  157. * Gets a song from id from Mongo and updates the cache with it
  158. *
  159. * @param {object} payload - an object containing the payload
  160. * @param {string} payload.songId - the id of the song we are trying to update
  161. * @returns {Promise} - returns a promise (resolve, reject)
  162. */
  163. UPDATE_SONG(payload) {
  164. // songId, cb
  165. return new Promise((resolve, reject) =>
  166. async.waterfall(
  167. [
  168. next => {
  169. SongsModule.songModel.findOne({ _id: payload.songId }, next);
  170. },
  171. (song, next) => {
  172. if (!song) {
  173. CacheModule.runJob("HDEL", {
  174. table: "songs",
  175. key: payload.songId
  176. });
  177. return next("Song not found.");
  178. }
  179. return CacheModule.runJob(
  180. "HSET",
  181. {
  182. table: "songs",
  183. key: payload.songId,
  184. value: song
  185. },
  186. this
  187. )
  188. .then(song => {
  189. next(null, song);
  190. })
  191. .catch(next);
  192. }
  193. ],
  194. (err, song) => {
  195. if (err && err !== true) return reject(new Error(err));
  196. return resolve(song);
  197. }
  198. )
  199. );
  200. }
  201. /**
  202. * Deletes song from id from Mongo and cache
  203. *
  204. * @param {object} payload - returns an object containing the payload
  205. * @param {string} payload.songId - the id of the song we are trying to delete
  206. * @returns {Promise} - returns a promise (resolve, reject)
  207. */
  208. DELETE_SONG(payload) {
  209. // songId, cb
  210. return new Promise((resolve, reject) =>
  211. async.waterfall(
  212. [
  213. next => {
  214. SongsModule.songModel.deleteOne({ songId: payload.songId }, next);
  215. },
  216. next => {
  217. CacheModule.runJob(
  218. "HDEL",
  219. {
  220. table: "songs",
  221. key: payload.songId
  222. },
  223. this
  224. )
  225. .then(() => next())
  226. .catch(next);
  227. }
  228. ],
  229. err => {
  230. if (err && err !== true) return reject(new Error(err));
  231. return resolve();
  232. }
  233. )
  234. );
  235. }
  236. }
  237. export default new _SongsModule();