playlists.js 11 KB

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