| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 | 'use strict';const coreClass = require("../core");const async = require('async');const mongoose = require('mongoose');module.exports = class extends coreClass {	constructor(name, moduleManager) {		super(name, moduleManager);		this.dependsOn = ["utils", "cache", "db"];	}	initialize() {		return new Promise((resolve, reject) => {			this.setStage(1);			this.cache = this.moduleManager.modules["cache"];			this.db = this.moduleManager.modules["db"];			this.io = this.moduleManager.modules["io"];			this.utils = this.moduleManager.modules["utils"];			async.waterfall([				(next) => {					this.setStage(2);					this.cache.hgetall('songs', next);				},					(songs, next) => {					this.setStage(3);					if (!songs) return next();					let songIds = Object.keys(songs);					async.each(songIds, (songId, next) => {						this.db.models.song.findOne({songId}, (err, song) => {							if (err) next(err);							else if (!song) this.cache.hdel('songs', songId, next);							else next();						});					}, next);				},					(next) => {					this.setStage(4);					this.db.models.song.find({}, next);				},					(songs, next) => {					this.setStage(5);					async.each(songs, (song, next) => {						this.cache.hset('songs', song.songId, this.cache.schemas.song(song), next);					}, next);				}			], async (err) => {				if (err) {					err = await this.utils.getError(err);					reject(err);				} else {					resolve();				}			});		});	}	/**	 * Gets a song by id from the cache or Mongo, and if it isn't in the cache yet, adds it the cache	 *	 * @param {String} id - the id of the song we are trying to get	 * @param {Function} cb - gets called once we're done initializing	 */	async getSong(id, cb) {		try { await this._validateHook(); } catch { return; }		async.waterfall([			(next) => {				if (!mongoose.Types.ObjectId.isValid(id)) return next('Id is not a valid ObjectId.');				this.cache.hget('songs', id, next);			},			(song, next) => {				if (song) return next(true, song);				this.db.models.song.findOne({_id: id}, next);			},			(song, next) => {				if (song) {					this.cache.hset('songs', id, song, next);				} else next('Song not found.');			},		], (err, song) => {			if (err && err !== true) return cb(err);			cb(null, song);		});	}	/**	 * Gets a song by song id from the cache or Mongo, and if it isn't in the cache yet, adds it the cache	 *	 * @param {String} songId - the mongo id of the song we are trying to get	 * @param {Function} cb - gets called once we're done initializing	 */	async getSongFromId(songId, cb) {		try { await this._validateHook(); } catch { return; }		async.waterfall([			(next) => {				this.db.models.song.findOne({ songId }, next);			}		], (err, song) => {			if (err && err !== true) return cb(err);			else return cb(null, song);		});	}	/**	 * Gets a song from id from Mongo and updates the cache with it	 *	 * @param {String} songId - the id of the song we are trying to update	 * @param {Function} cb - gets called when an error occurred or when the operation was successful	 */	async updateSong(songId, cb) {		try { await this._validateHook(); } catch { return; }		async.waterfall([			(next) => {				this.db.models.song.findOne({_id: songId}, next);			},			(song, next) => {				if (!song) {					this.cache.hdel('songs', songId);					return next('Song not found.');				}				this.cache.hset('songs', songId, song, next);			}		], (err, song) => {			if (err && err !== true) return cb(err);			cb(null, song);		});	}	/**	 * Deletes song from id from Mongo and cache	 *	 * @param {String} songId - the id of the song we are trying to delete	 * @param {Function} cb - gets called when an error occurred or when the operation was successful	 */	async deleteSong(songId, cb) {		try { await this._validateHook(); } catch { return; }		async.waterfall([			(next) => {				this.db.models.song.deleteOne({ songId }, next);			},			(next) => {				this.cache.hdel('songs', songId, next);			}		], (err) => {			if (err && err !== true) cb(err);			cb(null);		});	}}
 |