Quellcode durchsuchen

refactor(Ratings): Creation/removal handling improvements

Owen Diffey vor 2 Jahren
Ursprung
Commit
52955372bc

+ 1 - 1
backend/logic/actions/ratings.js

@@ -691,7 +691,7 @@ export default {
 		async.waterfall(
 			[
 				next => {
-					RatingsModule.runJob("GET_RATINGS", { youtubeId }, this)
+					RatingsModule.runJob("GET_RATINGS", { youtubeId, createMissing: true }, this)
 						.then(res => next(null, res.ratings))
 						.catch(next);
 				},

+ 10 - 3
backend/logic/actions/songs.js

@@ -12,6 +12,7 @@ const CacheModule = moduleManager.modules.cache;
 const SongsModule = moduleManager.modules.songs;
 const PlaylistsModule = moduleManager.modules.playlists;
 const StationsModule = moduleManager.modules.stations;
+const RatingsModule = moduleManager.modules.ratings;
 
 CacheModule.runJob("SUB", {
 	channel: "song.updated",
@@ -495,14 +496,14 @@ export default {
 								},
 								err => {
 									if (err) next(err);
-									else next();
+									else next(null, song);
 								}
 							);
 						}
 					});
 				},
 
-				next => {
+				(song, next) => {
 					stationModel.find({ "currentSong._id": songId }, (err, stations) => {
 						if (err) next(err);
 						else {
@@ -525,13 +526,19 @@ export default {
 								},
 								err => {
 									if (err) next(err);
-									else next();
+									else next(null, song);
 								}
 							);
 						}
 					});
 				},
 
+				(song, next) => {
+					RatingsModule.runJob("REMOVE_RATINGS", { youtubeIds: song.youtubeId }, this)
+						.then(() => next())
+						.catch(next);
+				},
+
 				next => {
 					songModel.deleteOne({ _id: songId }, err => {
 						if (err) next(err);

+ 60 - 5
backend/logic/ratings.js

@@ -216,6 +216,7 @@ class _RatingsModule extends CoreClass {
 	 *
 	 * @param {object} payload - object containing the payload
 	 * @param {string} payload.youtubeId - the youtube id
+	 * @param {string} payload.createMissing - whether to create missing ratings
 	 * @returns {Promise} - returns a promise (resolve, reject)
 	 */
 	GET_RATINGS(payload) {
@@ -233,8 +234,8 @@ class _RatingsModule extends CoreClass {
 					},
 
 					(ratings, next) => {
-						if (ratings) {
-							CacheModule.runJob(
+						if (ratings)
+							return CacheModule.runJob(
 								"HSET",
 								{
 									table: "ratings",
@@ -242,9 +243,19 @@ class _RatingsModule extends CoreClass {
 									value: ratings
 								},
 								this
-							).then(ratings => next(null, ratings));
-						} else next("Ratings not found.");
-					}
+							).then(ratings => next(true, ratings));
+
+						if (!payload.createMissing) return next("Ratings not found.");
+
+						return RatingsModule.runJob("RECALCULATE_RATINGS", { youtubeId: payload.youtubeId }, this)
+							.then(() => next())
+							.catch(next);
+					},
+
+					next =>
+						RatingsModule.runJob("GET_RATINGS", { youtubeId: payload.youtubeId }, this)
+							.then(res => next(null, res.ratings))
+							.catch(next)
 				],
 				(err, ratings) => {
 					if (err && err !== true) return reject(new Error(err));
@@ -253,6 +264,50 @@ class _RatingsModule extends CoreClass {
 			);
 		});
 	}
+
+	/**
+	 * Remove ratings by id from the cache and Mongo
+	 *
+	 * @param {object} payload - object containing the payload
+	 * @param {string} payload.youtubeIds - the youtube id
+	 * @returns {Promise} - returns a promise (resolve, reject)
+	 */
+	REMOVE_RATINGS(payload) {
+		return new Promise((resolve, reject) => {
+			let { youtubeIds } = payload;
+			if (!Array.isArray(youtubeIds)) youtubeIds = [youtubeIds];
+
+			async.eachLimit(
+				youtubeIds,
+				1,
+				(youtubeId, next) => {
+					async.waterfall(
+						[
+							next => {
+								RatingsModule.RatingsModel.deleteOne({ youtubeId }, err => {
+									if (err) next(err);
+									else next();
+								});
+							},
+
+							next => {
+								CacheModule.runJob("HDEL", { table: "ratings", key: youtubeId }, this)
+									.then(() => {
+										next();
+									})
+									.catch(next);
+							}
+						],
+						next
+					);
+				},
+				err => {
+					if (err && err !== true) return reject(new Error(err));
+					return resolve();
+				}
+			);
+		});
+	}
 }
 
 export default new _RatingsModule();

+ 8 - 0
backend/logic/songs.js

@@ -9,6 +9,7 @@ let UtilsModule;
 let YouTubeModule;
 let StationsModule;
 let PlaylistsModule;
+let RatingsModule;
 
 class _SongsModule extends CoreClass {
 	// eslint-disable-next-line require-jsdoc
@@ -32,6 +33,7 @@ class _SongsModule extends CoreClass {
 		YouTubeModule = this.moduleManager.modules.youtube;
 		StationsModule = this.moduleManager.modules.stations;
 		PlaylistsModule = this.moduleManager.modules.playlists;
+		RatingsModule = this.moduleManager.modules.ratings;
 
 		this.SongModel = await DBModule.runJob("GET_MODEL", { modelName: "song" });
 		this.SongSchemaCache = await CacheModule.runJob("GET_SCHEMA", { schemaName: "song" });
@@ -319,6 +321,12 @@ class _SongsModule extends CoreClass {
 					(song, next) => {
 						SongsModule.runJob("UPDATE_SONG", { songId: song._id });
 						return next(null, song);
+					},
+
+					(song, next) => {
+						RatingsModule.runJob("RECALCULATE_RATINGS", { youtubeId: song.youtubeId }, this)
+							.then(() => next(null, song))
+							.catch(next);
 					}
 				],
 				(err, song) => {

+ 34 - 3
backend/logic/youtube.js

@@ -43,6 +43,7 @@ class RateLimitter {
 let YouTubeModule;
 let CacheModule;
 let DBModule;
+let RatingsModule;
 
 const isQuotaExceeded = apiCalls => {
 	const reversedApiCalls = apiCalls.slice().reverse();
@@ -103,6 +104,7 @@ class _YouTubeModule extends CoreClass {
 		return new Promise(async resolve => {
 			CacheModule = this.moduleManager.modules.cache;
 			DBModule = this.moduleManager.modules.db;
+			RatingsModule = this.moduleManager.modules.ratings;
 
 			this.youtubeApiRequestModel = this.YoutubeApiRequestModel = await DBModule.runJob("GET_MODEL", {
 				modelName: "youtubeApiRequest"
@@ -987,6 +989,23 @@ class _YouTubeModule extends CoreClass {
 							if (!Array.isArray(youtubeVideos)) youtubeVideos = [youtubeVideos];
 							YouTubeModule.youtubeVideoModel.insertMany(youtubeVideos, next);
 						}
+					},
+
+					(youtubeVideos, next) => {
+						const youtubeIds = youtubeVideos.map(video => video.youtubeId);
+						async.eachLimit(
+							youtubeIds,
+							2,
+							(youtubeId, next) => {
+								RatingsModule.runJob("RECALCULATE_RATINGS", { youtubeId }, this)
+									.then(() => next())
+									.catch(next);
+							},
+							err => {
+								if (err) next(err);
+								else next(null, youtubeVideos);
+							}
+						);
 					}
 				],
 				(err, youtubeVideos) => {
@@ -1098,16 +1117,28 @@ class _YouTubeModule extends CoreClass {
 	 */
 	 REMOVE_VIDEOS(payload) {
 		return new Promise((resolve, reject) => {
+			let videoIds = payload.videoIds;
+			if (!Array.isArray(videoIds)) videoIds = [videoIds];
+
 			async.waterfall(
 				[
 					next => {
-						let videoIds = payload.videoIds;
-						if (!Array.isArray(videoIds)) videoIds = [videoIds];
 						if (!videoIds.every(videoId => mongoose.Types.ObjectId.isValid(videoId)))
 							next("One or more videoIds are not a valid ObjectId.");
 						else {
-							YouTubeModule.youtubeVideoModel.deleteMany({_id: { $in: videoIds }}, next);
+							YouTubeModule.youtubeVideoModel.find({_id: { $in: videoIds }}, next);
 						}
+					},
+
+					(videos, next) => {
+						const youtubeIds = videos.map(video => video.youtubeId);
+						RatingsModule.runJob("REMOVE_RATINGS", { youtubeIds }, this)
+							.then(() => next())
+							.catch(next);
+					},
+
+					next => {
+						YouTubeModule.youtubeVideoModel.deleteMany({_id: { $in: videoIds }}, next);
 					}
 				],
 				err => {