playlists.js 10 KB

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