playlists.js 6.4 KB

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