songs.js 6.2 KB

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