mirror of
https://github.com/sphildreth/roadie
synced 2024-11-10 06:44:12 +00:00
Performance timings and improvements.
This commit is contained in:
parent
6ff3a0004c
commit
17c29503af
19 changed files with 356 additions and 70 deletions
|
@ -31,6 +31,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Roadie.Api.Library\Roadie.Library.csproj" />
|
||||
<ProjectReference Include="..\Roadie.Api.Services\Roadie.Api.Services.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
31
Roadie.Api.Library.Tests/TokenHelperTests.cs
Normal file
31
Roadie.Api.Library.Tests/TokenHelperTests.cs
Normal file
|
@ -0,0 +1,31 @@
|
|||
using Roadie.Api.Services;
|
||||
using Roadie.Library.Identity;
|
||||
using Roadie.Library.MetaData.Audio;
|
||||
using Roadie.Library.MetaData.ID3Tags;
|
||||
using Roadie.Library.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Roadie.Library.Tests
|
||||
{
|
||||
public class TokenHelperTests
|
||||
{
|
||||
[Fact]
|
||||
public void GeneratePlayToken()
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
|
||||
var token = ServiceBase.TrackPlayToken(new ApplicationUser
|
||||
{
|
||||
Id = 1,
|
||||
CreatedDate = DateTime.UtcNow
|
||||
}, Guid.NewGuid());
|
||||
sw.Stop();
|
||||
|
||||
Assert.NotNull(token);
|
||||
}
|
||||
}
|
||||
}
|
27
Roadie.Api.Library/Extensions/DictionaryExt.cs
Normal file
27
Roadie.Api.Library/Extensions/DictionaryExt.cs
Normal file
|
@ -0,0 +1,27 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Roadie.Library.Extensions
|
||||
{
|
||||
public static class EnumerableExt
|
||||
{
|
||||
public static string ToTimings(this IDictionary<string, long> values)
|
||||
{
|
||||
if(values == null || !values.Any())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var timings = new List<string>
|
||||
{
|
||||
$" TOTAL: { values.Sum(x => x.Value) }"
|
||||
};
|
||||
foreach (var timing in values.OrderByDescending(x => x.Value).ThenBy(x => x.Key))
|
||||
{
|
||||
timings.Add($"{ timing.Key}: { timing.Value }");
|
||||
}
|
||||
return string.Join(", ", timings);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -365,5 +365,14 @@ namespace Roadie.Library.Extensions
|
|||
var uri = new Uri(input);
|
||||
return uri.Segments.Last();
|
||||
}
|
||||
|
||||
public static string ToCSV(this IEnumerable<string> input)
|
||||
{
|
||||
if(input == null || !input.Any())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return string.Join(",", input);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -118,5 +118,10 @@ namespace Roadie.Library.Models
|
|||
{
|
||||
BandStatus = "1";
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Id [{ Id }], Name [{ Name }]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -79,5 +79,10 @@ namespace Roadie.Library.Models.Releases
|
|||
|
||||
public short TrackCount { get; set; }
|
||||
public UserRelease UserRating { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Id [{ Id }], Title [{ Title }]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Roadie.Library.Models.Releases
|
||||
{
|
||||
|
@ -9,6 +10,6 @@ namespace Roadie.Library.Models.Releases
|
|||
public short? MediaNumber { get; set; }
|
||||
public string SubTitle { get; set; }
|
||||
public int? TrackCount { get; set; }
|
||||
public IEnumerable<TrackList> Tracks { get; set; }
|
||||
public IEnumerable<TrackList> Tracks { get; set; } = Enumerable.Empty<TrackList>();
|
||||
}
|
||||
}
|
|
@ -95,5 +95,10 @@ namespace Roadie.Library.Models
|
|||
|
||||
public string TrackPlayUrl { get; set; }
|
||||
public UserTrack UserRating { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Id [{ Id }], Title [{ Title }]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -123,26 +123,27 @@ namespace Roadie.Api.Services
|
|||
tsw.Restart();
|
||||
var artist = GetArtist(id);
|
||||
tsw.Stop();
|
||||
timings.Add("GetArtist", tsw.ElapsedMilliseconds);
|
||||
timings.Add("getArtist", tsw.ElapsedMilliseconds);
|
||||
tsw.Restart();
|
||||
var userBookmarkResult =
|
||||
await BookmarkService.List(roadieUser, new PagedRequest(), false, BookmarkType.Artist);
|
||||
if (userBookmarkResult.IsSuccess)
|
||||
result.Data.UserBookmarked =
|
||||
userBookmarkResult?.Rows?.FirstOrDefault(x => x.Bookmark.Value == artist.RoadieId.ToString()) !=
|
||||
null;
|
||||
{
|
||||
result.Data.UserBookmarked = userBookmarkResult?.Rows?.FirstOrDefault(x => x.Bookmark.Value == artist.RoadieId.ToString()) != null;
|
||||
}
|
||||
tsw.Stop();
|
||||
timings.Add("userBookmarkResult", tsw.ElapsedMilliseconds);
|
||||
tsw.Restart();
|
||||
var userArtist =
|
||||
DbContext.UserArtists.FirstOrDefault(x => x.ArtistId == artist.Id && x.UserId == roadieUser.Id);
|
||||
var userArtist = DbContext.UserArtists.FirstOrDefault(x => x.ArtistId == artist.Id && x.UserId == roadieUser.Id);
|
||||
if (userArtist != null)
|
||||
{
|
||||
result.Data.UserRating = new UserArtist
|
||||
{
|
||||
IsDisliked = userArtist.IsDisliked ?? false,
|
||||
IsFavorite = userArtist.IsFavorite ?? false,
|
||||
Rating = userArtist.Rating
|
||||
};
|
||||
}
|
||||
tsw.Stop();
|
||||
timings.Add("userArtist", tsw.ElapsedMilliseconds);
|
||||
|
||||
|
@ -156,21 +157,18 @@ namespace Roadie.Api.Services
|
|||
select cr).ToArray();
|
||||
foreach (var comment in result.Data.Comments)
|
||||
{
|
||||
var userCommentReaction =
|
||||
userCommentReactions.FirstOrDefault(x => x.CommentId == comment.DatabaseId);
|
||||
var userCommentReaction = userCommentReactions.FirstOrDefault(x => x.CommentId == comment.DatabaseId);
|
||||
comment.IsDisliked = userCommentReaction?.ReactionValue == CommentReaction.Dislike;
|
||||
comment.IsLiked = userCommentReaction?.ReactionValue == CommentReaction.Like;
|
||||
}
|
||||
|
||||
tsw.Stop();
|
||||
timings.Add("commentReactions", tsw.ElapsedMilliseconds);
|
||||
timings.Add("userCommentReactions", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
timings.Add("operation", sw.ElapsedMilliseconds);
|
||||
Logger.LogDebug("ById Timings: id [{0}], includes [{1}], timings [{3}]", id, includes,
|
||||
JsonConvert.SerializeObject(timings));
|
||||
Logger.LogInformation($"ById Artist: `{ result?.Data }`, includes [{ includes.ToCSV() }], timings [{ timings.ToTimings() }]");
|
||||
return new OperationResult<Artist>(result.Messages)
|
||||
{
|
||||
Data = result?.Data,
|
||||
|
@ -931,10 +929,10 @@ namespace Roadie.Api.Services
|
|||
? SafeParser.ToNumber<int?>(DbContext.Artists.Count(x => x.Rank > result.Rank) + 1)
|
||||
: null;
|
||||
tsw.Stop();
|
||||
timings.Add("adaptArtist", tsw.ElapsedMilliseconds);
|
||||
timings.Add("adapt", tsw.ElapsedMilliseconds);
|
||||
tsw.Restart();
|
||||
result.Thumbnail = MakeArtistThumbnailImage(id);
|
||||
result.MediumThumbnail = MakeThumbnailImage(id, "artist", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
|
||||
tsw.Restart();
|
||||
result.Genres = artist.Genres.Select(x => new DataToken
|
||||
{
|
||||
Text = x.Genre.Name,
|
||||
|
@ -945,6 +943,7 @@ namespace Roadie.Api.Services
|
|||
|
||||
if (includes != null && includes.Any())
|
||||
{
|
||||
tsw.Restart();
|
||||
if (includes.Contains("releases"))
|
||||
{
|
||||
var dtoReleases = new List<ReleaseList>();
|
||||
|
@ -991,6 +990,8 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
|
||||
result.Releases = dtoReleases;
|
||||
tsw.Stop();
|
||||
timings.Add("releases", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
if (includes.Contains("stats"))
|
||||
|
@ -1277,8 +1278,7 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
|
||||
sw.Stop();
|
||||
timings.Add("operation", sw.ElapsedMilliseconds);
|
||||
Logger.LogDebug("ArtistByIdAction Timings: id [{0}], includes [{1}], timings [{3}]", id, includes, JsonConvert.SerializeObject(timings));
|
||||
Logger.LogInformation($"ByIdAction: Artist `{ artist }`: includes [{includes.ToCSV() }], timings: [{ timings.ToTimings() }]");
|
||||
return new OperationResult<Artist>
|
||||
{
|
||||
Data = result,
|
||||
|
|
|
@ -113,7 +113,7 @@ namespace Roadie.Api.Services
|
|||
Text = track.Title,
|
||||
Value = track.RoadieId.ToString()
|
||||
};
|
||||
row.Track = models.TrackList.FromDataTrack(MakeTrackPlayUrl(user, track.Id, track.RoadieId),
|
||||
row.Track = models.TrackList.FromDataTrack(MakeTrackPlayUrl(user, HttpContext.BaseUrl, track.Id, track.RoadieId),
|
||||
track,
|
||||
track.ReleaseMedia.MediaNumber,
|
||||
track.ReleaseMedia.Release,
|
||||
|
@ -126,7 +126,7 @@ namespace Roadie.Api.Services
|
|||
MakeArtistThumbnailImage(track.TrackArtist == null
|
||||
? null
|
||||
: (Guid?)track.TrackArtist.RoadieId));
|
||||
row.Track.TrackPlayUrl = MakeTrackPlayUrl(user, track.Id, track.RoadieId);
|
||||
row.Track.TrackPlayUrl = MakeTrackPlayUrl(user, HttpContext.BaseUrl, track.Id, track.RoadieId);
|
||||
row.Thumbnail = MakeTrackThumbnailImage(track.RoadieId);
|
||||
row.SortName = track.Title;
|
||||
break;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using Roadie.Library;
|
||||
using Roadie.Library.Caching;
|
||||
using Roadie.Library.Configuration;
|
||||
|
@ -331,10 +332,16 @@ namespace Roadie.Api.Services
|
|||
|
||||
private Task<OperationResult<Collection>> CollectionByIdAction(Guid id, IEnumerable<string> includes = null)
|
||||
{
|
||||
var timings = new Dictionary<string, long>();
|
||||
var tsw = new Stopwatch();
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
sw.Start();
|
||||
|
||||
tsw.Restart();
|
||||
var collection = GetCollection(id);
|
||||
tsw.Stop();
|
||||
timings.Add("getCollection", tsw.ElapsedMilliseconds);
|
||||
|
||||
if (collection == null)
|
||||
{
|
||||
|
@ -355,6 +362,8 @@ namespace Roadie.Api.Services
|
|||
result.CollectionFoundCount = (from crc in DbContext.CollectionReleases
|
||||
where crc.CollectionId == collection.Id
|
||||
select crc.Id).Count();
|
||||
tsw.Stop();
|
||||
timings.Add("adapt", tsw.ElapsedMilliseconds);
|
||||
if (includes != null && includes.Any())
|
||||
{
|
||||
if (includes.Contains("list"))
|
||||
|
@ -369,6 +378,8 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
|
||||
if (includes.Contains("releases"))
|
||||
{
|
||||
tsw.Restart();
|
||||
result.Releases = (from crc in DbContext.CollectionReleases
|
||||
join r in DbContext.Releases.Include(x => x.Artist) on crc.ReleaseId equals r.Id
|
||||
where crc.CollectionId == collection.Id
|
||||
|
@ -378,9 +389,13 @@ namespace Roadie.Api.Services
|
|||
ListNumber = crc.ListNumber,
|
||||
Release = ReleaseList.FromDataRelease(r, r.Artist, HttpContext.BaseUrl, MakeArtistThumbnailImage(r.Artist.RoadieId), MakeReleaseThumbnailImage(r.RoadieId))
|
||||
}).ToArray();
|
||||
tsw.Stop();
|
||||
timings.Add("releases", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
if (includes.Contains("stats"))
|
||||
{
|
||||
tsw.Restart();
|
||||
var collectionReleases = from crc in DbContext.CollectionReleases
|
||||
join r in DbContext.Releases on crc.ReleaseId equals r.Id
|
||||
where crc.CollectionId == collection.Id
|
||||
|
@ -404,10 +419,13 @@ namespace Roadie.Api.Services
|
|||
TrackCount = collectionReleases.Sum(x => x.TrackCount),
|
||||
TrackPlayedCount = collectionReleases.Sum(x => x.PlayedCount)
|
||||
};
|
||||
tsw.Stop();
|
||||
timings.Add("stats", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
if (includes.Contains("comments"))
|
||||
{
|
||||
tsw.Restart();
|
||||
var collectionComments = DbContext.Comments.Include(x => x.User)
|
||||
.Where(x => x.CollectionId == collection.Id)
|
||||
.OrderByDescending(x => x.CreatedDate)
|
||||
|
@ -430,9 +448,11 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
result.Comments = comments;
|
||||
}
|
||||
tsw.Stop();
|
||||
timings.Add("comments", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
Logger.LogInformation($"ByIdAction: Collection `{ collection }`: includes [{includes.ToCSV()}], timings: [{ timings.ToTimings() }]");
|
||||
sw.Stop();
|
||||
return Task.FromResult(new OperationResult<Collection>
|
||||
{
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using Roadie.Library;
|
||||
using Roadie.Library.Caching;
|
||||
using Roadie.Library.Configuration;
|
||||
using Roadie.Library.Extensions;
|
||||
using Roadie.Library.Encoding;
|
||||
using Roadie.Library.Identity;
|
||||
using Roadie.Library.Imaging;
|
||||
|
@ -85,6 +87,9 @@ namespace Roadie.Api.Services
|
|||
|
||||
private Task<OperationResult<Genre>> GenreByIdAction(Guid id, IEnumerable<string> includes = null)
|
||||
{
|
||||
var timings = new Dictionary<string, long>();
|
||||
var tsw = new Stopwatch();
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
sw.Start();
|
||||
|
||||
|
@ -93,15 +98,22 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
return Task.FromResult(new OperationResult<Genre>(true, string.Format("Genre Not Found [{0}]", id)));
|
||||
}
|
||||
tsw.Stop();
|
||||
timings.Add("getGenre", tsw.ElapsedMilliseconds);
|
||||
|
||||
tsw.Restart();
|
||||
var result = genre.Adapt<Genre>();
|
||||
result.AlternateNames = genre.AlternateNames;
|
||||
result.Tags = genre.Tags;
|
||||
result.Thumbnail = MakeLabelThumbnailImage(genre.RoadieId);
|
||||
result.MediumThumbnail = MakeThumbnailImage(id, "genre", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
|
||||
tsw.Stop();
|
||||
timings.Add("adapt", tsw.ElapsedMilliseconds);
|
||||
if (includes != null && includes.Any())
|
||||
{
|
||||
if (includes.Contains("stats"))
|
||||
{
|
||||
tsw.Restart();
|
||||
var releaseCount = (from rg in DbContext.ReleaseGenres
|
||||
where rg.GenreId == genre.Id
|
||||
select rg.Id).Count();
|
||||
|
@ -113,9 +125,12 @@ namespace Roadie.Api.Services
|
|||
ArtistCount = artistCount,
|
||||
ReleaseCount = releaseCount
|
||||
};
|
||||
tsw.Stop();
|
||||
timings.Add("stats", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
}
|
||||
sw.Stop();
|
||||
Logger.LogInformation($"ByIdAction: Genre `{ genre }`: includes [{includes.ToCSV()}], timings: [{ timings.ToTimings() }]");
|
||||
return Task.FromResult(new OperationResult<Genre>
|
||||
{
|
||||
Data = result,
|
||||
|
|
|
@ -361,24 +361,34 @@ namespace Roadie.Api.Services
|
|||
|
||||
private Task<OperationResult<Label>> LabelByIdAction(Guid id, IEnumerable<string> includes = null)
|
||||
{
|
||||
var timings = new Dictionary<string, long>();
|
||||
var tsw = new Stopwatch();
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
sw.Start();
|
||||
|
||||
tsw.Restart();
|
||||
var label = GetLabel(id);
|
||||
|
||||
tsw.Stop();
|
||||
timings.Add("GetLabel", tsw.ElapsedMilliseconds);
|
||||
if (label == null)
|
||||
{
|
||||
return Task.FromResult(new OperationResult<Label>(true, string.Format("Label Not Found [{0}]", id)));
|
||||
|
||||
}
|
||||
tsw.Restart();
|
||||
var result = label.Adapt<Label>();
|
||||
result.AlternateNames = label.AlternateNames;
|
||||
result.Tags = label.Tags;
|
||||
result.URLs = label.URLs;
|
||||
result.Thumbnail = MakeLabelThumbnailImage(label.RoadieId);
|
||||
result.MediumThumbnail = MakeThumbnailImage(id, "label", Configuration.MediumImageSize.Width,Configuration.MediumImageSize.Height);
|
||||
tsw.Stop();
|
||||
timings.Add("adapt", tsw.ElapsedMilliseconds);
|
||||
if (includes != null && includes.Any())
|
||||
{
|
||||
if (includes.Contains("stats"))
|
||||
{
|
||||
tsw.Restart();
|
||||
var labelTracks = from l in DbContext.Labels
|
||||
join rl in DbContext.ReleaseLabels on l.Id equals rl.LabelId into rld
|
||||
from rl in rld.DefaultIfEmpty()
|
||||
|
@ -401,12 +411,17 @@ namespace Roadie.Api.Services
|
|||
TrackSize = result.DurationTime,
|
||||
FileSize = labelTracks.Sum(x => (long?)x.FileSize).ToFileSize()
|
||||
};
|
||||
tsw.Stop();
|
||||
timings.Add("stats", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
if (includes.Contains("comments"))
|
||||
{
|
||||
var labelComments = DbContext.Comments.Include(x => x.User).Where(x => x.LabelId == label.Id)
|
||||
.OrderByDescending(x => x.CreatedDate).ToArray();
|
||||
tsw.Restart();
|
||||
var labelComments = DbContext.Comments.Include(x => x.User)
|
||||
.Where(x => x.LabelId == label.Id)
|
||||
.OrderByDescending(x => x.CreatedDate)
|
||||
.ToArray();
|
||||
if (labelComments.Any())
|
||||
{
|
||||
var comments = new List<Comment>();
|
||||
|
@ -418,21 +433,20 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
var comment = labelComment.Adapt<Comment>();
|
||||
comment.DatabaseId = labelComment.Id;
|
||||
comment.User = UserList.FromDataUser(labelComment.User,
|
||||
MakeUserThumbnailImage(labelComment.User.RoadieId));
|
||||
comment.DislikedCount = userCommentReactions.Count(x =>
|
||||
x.CommentId == labelComment.Id && x.ReactionValue == CommentReaction.Dislike);
|
||||
comment.LikedCount = userCommentReactions.Count(x =>
|
||||
x.CommentId == labelComment.Id && x.ReactionValue == CommentReaction.Like);
|
||||
comment.User = UserList.FromDataUser(labelComment.User, MakeUserThumbnailImage(labelComment.User.RoadieId));
|
||||
comment.DislikedCount = userCommentReactions.Count(x => x.CommentId == labelComment.Id && x.ReactionValue == CommentReaction.Dislike);
|
||||
comment.LikedCount = userCommentReactions.Count(x => x.CommentId == labelComment.Id && x.ReactionValue == CommentReaction.Like);
|
||||
comments.Add(comment);
|
||||
}
|
||||
|
||||
result.Comments = comments;
|
||||
}
|
||||
tsw.Stop();
|
||||
timings.Add("stats", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
Logger.LogInformation($"ByIdAction: Label `{ label }`: includes [{includes.ToCSV()}], timings: [{ timings.ToTimings() }]");
|
||||
return Task.FromResult(new OperationResult<Label>
|
||||
{
|
||||
Data = result,
|
||||
|
|
|
@ -125,7 +125,7 @@ namespace Roadie.Api.Services
|
|||
var user = GetUser(roadieUser.UserId);
|
||||
foreach (var track in result.Data.Tracks)
|
||||
{
|
||||
track.Track.TrackPlayUrl = MakeTrackPlayUrl(user, track.Track.DatabaseId, track.Track.Id);
|
||||
track.Track.TrackPlayUrl = MakeTrackPlayUrl(user, HttpContext.BaseUrl, track.Track.DatabaseId, track.Track.Id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -444,15 +444,22 @@ namespace Roadie.Api.Services
|
|||
|
||||
private Task<OperationResult<Playlist>> PlaylistByIdAction(Guid id, IEnumerable<string> includes = null)
|
||||
{
|
||||
var timings = new Dictionary<string, long>();
|
||||
var tsw = new Stopwatch();
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
sw.Start();
|
||||
|
||||
tsw.Restart();
|
||||
var playlist = GetPlaylist(id);
|
||||
tsw.Stop();
|
||||
timings.Add("getPlaylist", tsw.ElapsedMilliseconds);
|
||||
|
||||
if (playlist == null)
|
||||
{
|
||||
return Task.FromResult(new OperationResult<Playlist>(true, string.Format("Playlist Not Found [{0}]", id)));
|
||||
}
|
||||
tsw.Restart();
|
||||
var result = playlist.Adapt<Playlist>();
|
||||
result.AlternateNames = playlist.AlternateNames;
|
||||
result.Tags = playlist.Tags;
|
||||
|
@ -461,6 +468,8 @@ namespace Roadie.Api.Services
|
|||
result.Maintainer = UserList.FromDataUser(maintainer, MakeUserThumbnailImage(maintainer.RoadieId));
|
||||
result.Thumbnail = MakePlaylistThumbnailImage(playlist.RoadieId);
|
||||
result.MediumThumbnail = MakeThumbnailImage(id, "playlist", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
|
||||
tsw.Stop();
|
||||
timings.Add("adapt", tsw.ElapsedMilliseconds);
|
||||
if (includes != null && includes.Any())
|
||||
{
|
||||
var playlistTracks = (from pl in DbContext.Playlists
|
||||
|
@ -471,6 +480,7 @@ namespace Roadie.Api.Services
|
|||
|
||||
if (includes.Contains("stats"))
|
||||
{
|
||||
tsw.Restart();
|
||||
result.Statistics = new ReleaseGroupingStatistics
|
||||
{
|
||||
ReleaseCount = result.ReleaseCount,
|
||||
|
@ -478,9 +488,12 @@ namespace Roadie.Api.Services
|
|||
TrackSize = result.DurationTime,
|
||||
FileSize = playlistTracks.Sum(x => (long?)x.t.FileSize).ToFileSize()
|
||||
};
|
||||
tsw.Stop();
|
||||
timings.Add("stats", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
if (includes.Contains("tracks"))
|
||||
{
|
||||
tsw.Restart();
|
||||
result.Tracks = (from plt in playlistTracks
|
||||
join rm in DbContext.ReleaseMedias on plt.t.ReleaseMediaId equals rm.Id
|
||||
join r in DbContext.Releases on rm.ReleaseId equals r.Id
|
||||
|
@ -502,9 +515,12 @@ namespace Roadie.Api.Services
|
|||
MakeArtistThumbnailImage(releaseArtist.RoadieId),
|
||||
MakeArtistThumbnailImage(trackArtist == null ? null : (Guid?)trackArtist.RoadieId))
|
||||
}).ToArray();
|
||||
tsw.Stop();
|
||||
timings.Add("tracks", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
if (includes.Contains("comments"))
|
||||
{
|
||||
tsw.Restart();
|
||||
var playlistComments = DbContext.Comments.Include(x => x.User)
|
||||
.Where(x => x.PlaylistId == playlist.Id)
|
||||
.OrderByDescending(x => x.CreatedDate)
|
||||
|
@ -527,10 +543,13 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
result.Comments = comments;
|
||||
}
|
||||
tsw.Stop();
|
||||
timings.Add("comments", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
Logger.LogInformation($"ByIdAction: Playlist `{ playlist }`: includes [{includes.ToCSV()}], timings: [{ timings.ToTimings() }]");
|
||||
return Task.FromResult(new OperationResult<Playlist>
|
||||
{
|
||||
Data = result,
|
||||
|
|
|
@ -25,6 +25,7 @@ using Roadie.Library.Models.Users;
|
|||
using Roadie.Library.Processors;
|
||||
using Roadie.Library.Utility;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
@ -102,13 +103,28 @@ namespace Roadie.Api.Services
|
|||
|
||||
public async Task<OperationResult<Release>> ById(User roadieUser, Guid id, IEnumerable<string> includes = null)
|
||||
{
|
||||
var timings = new Dictionary<string, long>();
|
||||
var tsw = new Stopwatch();
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
sw.Start();
|
||||
var cacheKey = string.Format("urn:release_by_id_operation:{0}:{1}", id, includes == null ? "0" : string.Join("|", includes));
|
||||
var result = await CacheManager.GetAsync(cacheKey,async () => { return await ReleaseByIdAction(id, includes); }, data.Artist.CacheRegionUrn(id));
|
||||
var result = await CacheManager.GetAsync(cacheKey,async () =>
|
||||
{
|
||||
tsw.Restart();
|
||||
var rr = await ReleaseByIdAction(id, includes);
|
||||
tsw.Stop();
|
||||
timings.Add("ReleaseByIdAction", tsw.ElapsedMilliseconds);
|
||||
return rr;
|
||||
|
||||
}, data.Artist.CacheRegionUrn(id));
|
||||
if (result?.Data != null && roadieUser != null)
|
||||
{
|
||||
tsw.Restart();
|
||||
var release = GetRelease(id);
|
||||
tsw.Stop();
|
||||
timings.Add("getRelease", tsw.ElapsedMilliseconds);
|
||||
|
||||
var userBookmarkResult = await BookmarkService.List(roadieUser, new PagedRequest(), false, BookmarkType.Release);
|
||||
if (userBookmarkResult.IsSuccess)
|
||||
{
|
||||
|
@ -116,19 +132,26 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
if (result.Data.Medias != null)
|
||||
{
|
||||
tsw.Restart();
|
||||
var user = GetUser(roadieUser.UserId);
|
||||
foreach (var media in result.Data.Medias)
|
||||
tsw.Stop();
|
||||
timings.Add("getUser", tsw.ElapsedMilliseconds);
|
||||
|
||||
tsw.Restart();
|
||||
Parallel.ForEach(result.Data.Medias.SelectMany(x => x.Tracks), track =>
|
||||
{
|
||||
foreach (var track in media.Tracks)
|
||||
{
|
||||
track.TrackPlayUrl = MakeTrackPlayUrl(user, track.DatabaseId, track.Id);
|
||||
}
|
||||
}
|
||||
var releaseTrackIds = result.Data.Medias.SelectMany(x => x.Tracks).Select(x => x.Id);
|
||||
track.TrackPlayUrl = MakeTrackPlayUrl(user, HttpContext.BaseUrl, track.DatabaseId, track.Id);
|
||||
});
|
||||
|
||||
tsw.Stop();
|
||||
timings.Add("makeTrackPlayUrls", tsw.ElapsedMilliseconds);
|
||||
|
||||
tsw.Restart();
|
||||
var releaseTrackIds = result.Data.Medias.SelectMany(x => x.Tracks).Select(x => x.Id).ToList();
|
||||
var releaseUserTracks = (from ut in DbContext.UserTracks
|
||||
join t in DbContext.Tracks on ut.TrackId equals t.Id
|
||||
where releaseTrackIds.Contains(t.RoadieId)
|
||||
where ut.UserId == roadieUser.Id
|
||||
where (from x in releaseTrackIds select x).Contains(t.RoadieId)
|
||||
select new
|
||||
{
|
||||
t,
|
||||
|
@ -142,6 +165,7 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
var releaseTrack = media.Tracks.FirstOrDefault(x => x.Id == releaseUserTrack.t.RoadieId);
|
||||
if (releaseTrack != null)
|
||||
{
|
||||
releaseTrack.UserRating = new UserTrack
|
||||
{
|
||||
Rating = releaseUserTrack.ut.Rating,
|
||||
|
@ -150,23 +174,30 @@ namespace Roadie.Api.Services
|
|||
LastPlayed = releaseUserTrack.ut.LastPlayed,
|
||||
PlayedCount = releaseUserTrack.ut.PlayedCount
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
tsw.Stop();
|
||||
timings.Add("userTracks", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
var userRelease = DbContext.UserReleases.FirstOrDefault(x => x.ReleaseId == release.Id && x.UserId == roadieUser.Id);
|
||||
if (userRelease != null)
|
||||
{
|
||||
tsw.Restart();
|
||||
result.Data.UserRating = new UserRelease
|
||||
{
|
||||
IsDisliked = userRelease.IsDisliked ?? false,
|
||||
IsFavorite = userRelease.IsFavorite ?? false,
|
||||
Rating = userRelease.Rating
|
||||
};
|
||||
tsw.Stop();
|
||||
timings.Add("userRelease", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
if (result.Data.Comments.Any())
|
||||
{
|
||||
tsw.Restart();
|
||||
var commentIds = result.Data.Comments.Select(x => x.DatabaseId).ToArray();
|
||||
var userCommentReactions = (from cr in DbContext.CommentReactions
|
||||
where commentIds.Contains(cr.CommentId)
|
||||
|
@ -178,10 +209,13 @@ namespace Roadie.Api.Services
|
|||
comment.IsDisliked = userCommentReaction?.ReactionValue == CommentReaction.Dislike;
|
||||
comment.IsLiked = userCommentReaction?.ReactionValue == CommentReaction.Like;
|
||||
}
|
||||
tsw.Stop();
|
||||
timings.Add("userComments", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
Logger.LogInformation($"ById Release: `{ result?.Data }`, includes [{ includes.ToCSV() }], timings [{ timings.ToTimings() }]");
|
||||
return new OperationResult<Release>(result.Messages)
|
||||
{
|
||||
Data = result?.Data,
|
||||
|
@ -1659,15 +1693,22 @@ namespace Roadie.Api.Services
|
|||
|
||||
private async Task<OperationResult<Release>> ReleaseByIdAction(Guid id, IEnumerable<string> includes = null)
|
||||
{
|
||||
var timings = new Dictionary<string, long>();
|
||||
var tsw = new Stopwatch();
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
sw.Start();
|
||||
|
||||
tsw.Restart();
|
||||
var release = GetRelease(id);
|
||||
tsw.Stop();
|
||||
timings.Add("getRelease", tsw.ElapsedMilliseconds);
|
||||
|
||||
if (release == null)
|
||||
{
|
||||
return new OperationResult<Release>(true, string.Format("Release Not Found [{0}]", id));
|
||||
}
|
||||
tsw.Restart();
|
||||
var result = release.Adapt<Release>();
|
||||
result.Artist = ArtistList.FromDataArtist(release.Artist, MakeArtistThumbnailImage(release.Artist.RoadieId));
|
||||
result.Thumbnail = MakeReleaseThumbnailImage(release.RoadieId);
|
||||
|
@ -1685,8 +1726,11 @@ namespace Roadie.Api.Services
|
|||
result.RankPosition = result.Rank > 0
|
||||
? SafeParser.ToNumber<int?>(DbContext.Releases.Count(x => x.Rank > result.Rank) + 1)
|
||||
: null;
|
||||
tsw.Stop();
|
||||
timings.Add("adapt", tsw.ElapsedMilliseconds);
|
||||
if (release.SubmissionId.HasValue)
|
||||
{
|
||||
tsw.Restart();
|
||||
var submission = DbContext.Submissions.Include(x => x.User).FirstOrDefault(x => x.Id == release.SubmissionId);
|
||||
if (submission != null)
|
||||
{
|
||||
|
@ -1704,20 +1748,27 @@ namespace Roadie.Api.Services
|
|||
};
|
||||
}
|
||||
}
|
||||
tsw.Stop();
|
||||
timings.Add("submissions", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
|
||||
if (includes != null && includes.Any())
|
||||
{
|
||||
if (includes.Contains("genres"))
|
||||
{
|
||||
tsw.Restart();
|
||||
result.Genres = release.Genres.Select(x => new DataToken
|
||||
{
|
||||
Text = x.Genre.Name,
|
||||
Value = x.Genre.RoadieId.ToString()
|
||||
});
|
||||
tsw.Stop();
|
||||
timings.Add("genres", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
if (includes.Contains("stats"))
|
||||
{
|
||||
tsw.Restart();
|
||||
var releaseTracks = from r in DbContext.Releases
|
||||
join rm in DbContext.ReleaseMedias on r.Id equals rm.ReleaseId
|
||||
join t in DbContext.Tracks on rm.Id equals t.ReleaseMediaId
|
||||
|
@ -1750,10 +1801,13 @@ namespace Roadie.Api.Services
|
|||
result.MaxMediaNumber = releaseMedias.Any() ? releaseMedias.Max(x => x.MediaNumber) : (short)0;
|
||||
result.Statistics = releaseStats;
|
||||
result.MediaCount = release.MediaCount ?? (short?)releaseStats?.MediaCount;
|
||||
tsw.Stop();
|
||||
timings.Add("stats", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
if (includes.Contains("images"))
|
||||
{
|
||||
tsw.Restart();
|
||||
var releaseImages = DbContext.Images.Where(x => x.ReleaseId == release.Id).Select(x => MakeFullsizeImage(x.RoadieId, x.Caption)).ToArray();
|
||||
if (releaseImages != null && releaseImages.Any())
|
||||
{
|
||||
|
@ -1766,20 +1820,26 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
result.Images = result.Images.Concat(releaseImagesInFolder.Select((x, i) => MakeFullsizeSecondaryImage(id, ImageType.ReleaseSecondary, i)));
|
||||
}
|
||||
tsw.Stop();
|
||||
timings.Add("images", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
if (includes.Contains("playlists"))
|
||||
{
|
||||
tsw.Restart();
|
||||
var pg = new PagedRequest
|
||||
{
|
||||
FilterToReleaseId = release.RoadieId
|
||||
};
|
||||
var r = await PlaylistService.List(pg);
|
||||
if (r.IsSuccess) result.Playlists = r.Rows.ToArray();
|
||||
tsw.Stop();
|
||||
timings.Add("playlists", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
if (includes.Contains("labels"))
|
||||
{
|
||||
tsw.Restart();
|
||||
var releaseLabels = (from l in DbContext.Labels
|
||||
join rl in DbContext.ReleaseLabels on l.Id equals rl.LabelId
|
||||
where rl.ReleaseId == release.Id
|
||||
|
@ -1823,10 +1883,13 @@ namespace Roadie.Api.Services
|
|||
|
||||
result.Labels = labels;
|
||||
}
|
||||
tsw.Stop();
|
||||
timings.Add("labels", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
if (includes.Contains("collections"))
|
||||
{
|
||||
tsw.Restart();
|
||||
var releaseCollections = DbContext.CollectionReleases.Include(x => x.Collection)
|
||||
.Where(x => x.ReleaseId == release.Id)
|
||||
.OrderBy(x => x.ListNumber)
|
||||
|
@ -1864,10 +1927,13 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
result.Collections = collections;
|
||||
}
|
||||
tsw.Stop();
|
||||
timings.Add("collections", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
if (includes.Contains("comments"))
|
||||
{
|
||||
tsw.Restart();
|
||||
var releaseComments = DbContext.Comments.Include(x => x.User)
|
||||
.Where(x => x.ReleaseId == release.Id)
|
||||
.OrderByDescending(x => x.CreatedDate)
|
||||
|
@ -1890,10 +1956,13 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
result.Comments = comments;
|
||||
}
|
||||
tsw.Stop();
|
||||
timings.Add("comments", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
if (includes.Contains("tracks"))
|
||||
{
|
||||
tsw.Restart();
|
||||
var releaseMedias = new List<ReleaseMediaList>();
|
||||
foreach (var releaseMedia in release.Medias.OrderBy(x => x.MediaNumber))
|
||||
{
|
||||
|
@ -1919,12 +1988,14 @@ namespace Roadie.Api.Services
|
|||
rm.Tracks = rmTracks;
|
||||
releaseMedias.Add(rm);
|
||||
}
|
||||
|
||||
result.Medias = releaseMedias;
|
||||
tsw.Stop();
|
||||
timings.Add("tracks", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
Logger.LogInformation($"ByIdAction: Release `{ release }`: includes [{includes.ToCSV()}], timings: [{ timings.ToTimings() }]");
|
||||
return new OperationResult<Release>
|
||||
{
|
||||
Data = result,
|
||||
|
|
|
@ -22,6 +22,11 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
public static string TrackTokenSalt = "B0246908-FBD6-4E12-A96C-AF5B086115B3";
|
||||
|
||||
private static readonly Lazy<Hashids> hashIds = new Lazy<Hashids>(() =>
|
||||
{
|
||||
return new Hashids(TrackTokenSalt);
|
||||
});
|
||||
|
||||
protected readonly ICacheManager _cacheManager;
|
||||
protected readonly IRoadieSettings _configuration;
|
||||
protected readonly data.IRoadieDbContext _dbContext;
|
||||
|
@ -54,16 +59,21 @@ namespace Roadie.Api.Services
|
|||
|
||||
public static bool ConfirmTrackPlayToken(ApplicationUser user, Guid trackRoadieId, string token)
|
||||
{
|
||||
if (string.IsNullOrEmpty(token)) return false;
|
||||
if (string.IsNullOrEmpty(token))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return TrackPlayToken(user, trackRoadieId).Equals(token);
|
||||
}
|
||||
|
||||
public static string TrackPlayToken(ApplicationUser user, Guid trackId)
|
||||
{
|
||||
var hashids = new Hashids(TrackTokenSalt);
|
||||
var trackIdPart = BitConverter.ToInt32(trackId.ToByteArray(), 6);
|
||||
if (trackIdPart < 0) trackIdPart *= -1;
|
||||
var token = hashids.Encode(user.Id, SafeParser.ToNumber<int>(user.CreatedDate.Value.ToString("DDHHmmss")), trackIdPart);
|
||||
if (trackIdPart < 0)
|
||||
{
|
||||
trackIdPart *= -1;
|
||||
}
|
||||
var token = hashIds.Value.Encode(user.Id, SafeParser.ToNumber<int>(user.CreatedDate.Value.ToString("DDHHmmss")), trackIdPart);
|
||||
return token;
|
||||
}
|
||||
|
||||
|
@ -279,10 +289,9 @@ namespace Roadie.Api.Services
|
|||
return MakeThumbnailImage(id, "release");
|
||||
}
|
||||
|
||||
protected string MakeTrackPlayUrl(ApplicationUser user, int trackId, Guid trackRoadieId)
|
||||
public static string MakeTrackPlayUrl(ApplicationUser user, string baseUrl, int trackId, Guid trackRoadieId)
|
||||
{
|
||||
return
|
||||
$"{HttpContext.BaseUrl}/play/track/{user.Id}/{TrackPlayToken(user, trackRoadieId)}/{trackRoadieId}.mp3";
|
||||
return $"{baseUrl}/play/track/{user.Id}/{TrackPlayToken(user, trackRoadieId)}/{trackRoadieId}.mp3";
|
||||
}
|
||||
|
||||
protected Image MakeTrackThumbnailImage(Guid id)
|
||||
|
|
|
@ -102,28 +102,48 @@ namespace Roadie.Api.Services
|
|||
|
||||
public async Task<OperationResult<Track>> ById(User roadieUser, Guid id, IEnumerable<string> includes)
|
||||
{
|
||||
var timings = new Dictionary<string, long>();
|
||||
var tsw = new Stopwatch();
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
sw.Start();
|
||||
var cacheKey = string.Format("urn:track_by_id_operation:{0}:{1}", id,
|
||||
includes == null ? "0" : string.Join("|", includes));
|
||||
var result = await CacheManager.GetAsync(cacheKey,
|
||||
async () => { return await TrackByIdAction(id, includes); }, data.Track.CacheRegionUrn(id));
|
||||
var cacheKey = string.Format("urn:track_by_id_operation:{0}:{1}", id, includes == null ? "0" : string.Join("|", includes));
|
||||
var result = await CacheManager.GetAsync(cacheKey, async () =>
|
||||
{
|
||||
tsw.Restart();
|
||||
var rr = await TrackByIdAction(id, includes);
|
||||
tsw.Stop();
|
||||
timings.Add("TrackByIdAction", tsw.ElapsedMilliseconds);
|
||||
return rr;
|
||||
|
||||
}, data.Track.CacheRegionUrn(id));
|
||||
if (result?.Data != null && roadieUser != null)
|
||||
{
|
||||
tsw.Restart();
|
||||
var user = GetUser(roadieUser.UserId);
|
||||
tsw.Stop();
|
||||
timings.Add("getUser", tsw.ElapsedMilliseconds);
|
||||
|
||||
tsw.Restart();
|
||||
var track = GetTrack(id);
|
||||
result.Data.TrackPlayUrl = MakeTrackPlayUrl(user, track.Id, track.RoadieId);
|
||||
var userBookmarkResult =
|
||||
await BookmarkService.List(roadieUser, new PagedRequest(), false, BookmarkType.Track);
|
||||
tsw.Stop();
|
||||
timings.Add("getTrack", tsw.ElapsedMilliseconds);
|
||||
|
||||
result.Data.TrackPlayUrl = MakeTrackPlayUrl(user, HttpContext.BaseUrl, track.Id, track.RoadieId);
|
||||
|
||||
tsw.Restart();
|
||||
var userBookmarkResult = await BookmarkService.List(roadieUser, new PagedRequest(), false, BookmarkType.Track);
|
||||
if (userBookmarkResult.IsSuccess)
|
||||
{
|
||||
result.Data.UserBookmarked =
|
||||
userBookmarkResult?.Rows?.FirstOrDefault(x => x.Bookmark.Value == track.RoadieId.ToString()) !=
|
||||
null;
|
||||
}
|
||||
tsw.Stop();
|
||||
timings.Add("userBookmarks", tsw.ElapsedMilliseconds);
|
||||
|
||||
var userTrack =
|
||||
DbContext.UserTracks.FirstOrDefault(x => x.TrackId == track.Id && x.UserId == roadieUser.Id);
|
||||
tsw.Restart();
|
||||
var userTrack = DbContext.UserTracks.FirstOrDefault(x => x.TrackId == track.Id && x.UserId == roadieUser.Id);
|
||||
if (userTrack != null)
|
||||
{
|
||||
result.Data.UserRating = new UserTrack
|
||||
|
@ -135,9 +155,13 @@ namespace Roadie.Api.Services
|
|||
PlayedCount = userTrack.PlayedCount
|
||||
};
|
||||
}
|
||||
tsw.Stop();
|
||||
timings.Add("userTracks", tsw.ElapsedMilliseconds);
|
||||
|
||||
|
||||
if (result.Data.Comments.Any())
|
||||
{
|
||||
tsw.Restart();
|
||||
var commentIds = result.Data.Comments.Select(x => x.DatabaseId).ToArray();
|
||||
var userCommentReactions = (from cr in DbContext.CommentReactions
|
||||
where commentIds.Contains(cr.CommentId)
|
||||
|
@ -150,10 +174,13 @@ namespace Roadie.Api.Services
|
|||
comment.IsDisliked = userCommentReaction?.ReactionValue == CommentReaction.Dislike;
|
||||
comment.IsLiked = userCommentReaction?.ReactionValue == CommentReaction.Like;
|
||||
}
|
||||
tsw.Stop();
|
||||
timings.Add("userComments", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
Logger.LogInformation($"ById Track: `{ result?.Data }`, includes [{ includes.ToCSV() }], timings [{ timings.ToTimings() }]");
|
||||
return new OperationResult<Track>(result.Messages)
|
||||
{
|
||||
Data = result?.Data,
|
||||
|
@ -541,7 +568,7 @@ namespace Roadie.Api.Services
|
|||
TrackNumber = playListTrackPositions.ContainsKey(x.ti.Id)
|
||||
? playListTrackPositions[x.ti.Id]
|
||||
: x.ti.TrackNumber,
|
||||
TrackPlayUrl = MakeTrackPlayUrl(user, x.ti.Id, x.ti.RoadieId)
|
||||
TrackPlayUrl = MakeTrackPlayUrl(user, HttpContext.BaseUrl, x.ti.Id, x.ti.RoadieId)
|
||||
});
|
||||
string sortBy = null;
|
||||
|
||||
|
@ -926,16 +953,22 @@ namespace Roadie.Api.Services
|
|||
|
||||
private Task<OperationResult<Track>> TrackByIdAction(Guid id, IEnumerable<string> includes)
|
||||
{
|
||||
var timings = new Dictionary<string, long>();
|
||||
var tsw = new Stopwatch();
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
sw.Start();
|
||||
|
||||
tsw.Restart();
|
||||
var track = GetTrack(id);
|
||||
tsw.Stop();
|
||||
timings.Add("getTrack", tsw.ElapsedMilliseconds);
|
||||
|
||||
if (track == null)
|
||||
{
|
||||
return Task.FromResult(new OperationResult<Track>(true, string.Format("Track Not Found [{0}]", id)));
|
||||
}
|
||||
|
||||
tsw.Restart();
|
||||
var result = track.Adapt<Track>();
|
||||
result.IsLocked = (track.IsLocked ?? false) ||
|
||||
(track.ReleaseMedia.IsLocked ?? false) ||
|
||||
|
@ -952,8 +985,11 @@ namespace Roadie.Api.Services
|
|||
HttpContext.BaseUrl, MakeArtistThumbnailImage(track.ReleaseMedia.Release.Artist.RoadieId),
|
||||
MakeReleaseThumbnailImage(track.ReleaseMedia.Release.RoadieId));
|
||||
result.ReleaseThumbnail = MakeReleaseThumbnailImage(track.ReleaseMedia.Release.RoadieId);
|
||||
tsw.Stop();
|
||||
timings.Add("adapt", tsw.ElapsedMilliseconds);
|
||||
if (track.ArtistId.HasValue)
|
||||
{
|
||||
tsw.Restart();
|
||||
var trackArtist = DbContext.Artists.FirstOrDefault(x => x.Id == track.ArtistId);
|
||||
if (trackArtist == null)
|
||||
{
|
||||
|
@ -966,12 +1002,15 @@ namespace Roadie.Api.Services
|
|||
result.TrackArtistToken = result.TrackArtist.Artist;
|
||||
result.TrackArtistThumbnail = MakeArtistThumbnailImage(trackArtist.RoadieId);
|
||||
}
|
||||
tsw.Stop();
|
||||
timings.Add("trackArtist", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
if (includes != null && includes.Any())
|
||||
{
|
||||
if (includes.Contains("stats"))
|
||||
{
|
||||
tsw.Restart();
|
||||
result.Statistics = new TrackStatistics
|
||||
{
|
||||
FileSizeFormatted = ((long?)track.FileSize).ToFileSize(),
|
||||
|
@ -987,10 +1026,13 @@ namespace Roadie.Api.Services
|
|||
result.Statistics.DislikedCount = userTracks.Count(x => x.IsDisliked ?? false);
|
||||
result.Statistics.FavoriteCount = userTracks.Count(x => x.IsFavorite ?? false);
|
||||
}
|
||||
tsw.Stop();
|
||||
timings.Add("stats", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
if (includes.Contains("comments"))
|
||||
{
|
||||
tsw.Restart();
|
||||
var trackComments = DbContext.Comments.Include(x => x.User).Where(x => x.TrackId == track.Id)
|
||||
.OrderByDescending(x => x.CreatedDate).ToArray();
|
||||
if (trackComments.Any())
|
||||
|
@ -1015,10 +1057,13 @@ namespace Roadie.Api.Services
|
|||
|
||||
result.Comments = comments;
|
||||
}
|
||||
tsw.Stop();
|
||||
timings.Add("comments", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
Logger.LogInformation($"ByIdAction: Track `{ track }`: includes [{includes.ToCSV()}], timings: [{ timings.ToTimings() }]");
|
||||
return Task.FromResult(new OperationResult<Track>
|
||||
{
|
||||
Data = result,
|
||||
|
|
|
@ -8,6 +8,7 @@ using Roadie.Library.Caching;
|
|||
using Roadie.Library.Configuration;
|
||||
using Roadie.Library.Encoding;
|
||||
using Roadie.Library.Enums;
|
||||
using Roadie.Library.Extensions;
|
||||
using Roadie.Library.Identity;
|
||||
using Roadie.Library.Imaging;
|
||||
using Roadie.Library.MetaData.LastFm;
|
||||
|
@ -52,8 +53,6 @@ namespace Roadie.Api.Services
|
|||
|
||||
public async Task<OperationResult<User>> ById(User user, Guid id, IEnumerable<string> includes, bool isAccountSettingsEdit = false)
|
||||
{
|
||||
var timings = new Dictionary<string, long>();
|
||||
var tsw = new Stopwatch();
|
||||
if(isAccountSettingsEdit)
|
||||
{
|
||||
if(user.UserId != id && !user.IsAdmin)
|
||||
|
@ -68,10 +67,7 @@ namespace Roadie.Api.Services
|
|||
var cacheKey = string.Format("urn:user_by_id_operation:{0}:{1}", id, isAccountSettingsEdit);
|
||||
var result = await CacheManager.GetAsync(cacheKey, async () =>
|
||||
{
|
||||
tsw.Restart();
|
||||
var rr = await UserByIdAction(id, includes);
|
||||
tsw.Stop();
|
||||
timings.Add("UserByIdAction", tsw.ElapsedMilliseconds);
|
||||
return rr;
|
||||
}, ApplicationUser.CacheRegionUrn(id));
|
||||
sw.Stop();
|
||||
|
@ -84,8 +80,6 @@ namespace Roadie.Api.Services
|
|||
result.Data.ConcurrencyStamp = null;
|
||||
}
|
||||
}
|
||||
timings.Add("operation", sw.ElapsedMilliseconds);
|
||||
Logger.LogDebug("ById Timings: id [{0}]", id);
|
||||
return new OperationResult<User>(result.Messages)
|
||||
{
|
||||
Data = result?.Data,
|
||||
|
@ -557,19 +551,31 @@ namespace Roadie.Api.Services
|
|||
|
||||
private Task<OperationResult<User>> UserByIdAction(Guid id, IEnumerable<string> includes)
|
||||
{
|
||||
var timings = new Dictionary<string, long>();
|
||||
var tsw = new Stopwatch();
|
||||
|
||||
tsw.Restart();
|
||||
var user = GetUser(id);
|
||||
tsw.Stop();
|
||||
timings.Add("getUser", tsw.ElapsedMilliseconds);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
return Task.FromResult(new OperationResult<User>(true, string.Format("User Not Found [{0}]", id)));
|
||||
}
|
||||
tsw.Restart();
|
||||
var model = user.Adapt<User>();
|
||||
model.MediumThumbnail = MakeThumbnailImage(id, "user", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
|
||||
model.IsAdmin = user.UserRoles?.Any(x => x.Role?.NormalizedName == "ADMIN") ?? false;
|
||||
model.IsEditor = model.IsAdmin ? true : user.UserRoles?.Any(x => x.Role?.NormalizedName == "EDITOR") ?? false;
|
||||
tsw.Stop();
|
||||
timings.Add("adapt", tsw.ElapsedMilliseconds);
|
||||
|
||||
if (includes != null && includes.Any())
|
||||
{
|
||||
if (includes.Contains("stats"))
|
||||
{
|
||||
tsw.Restart();
|
||||
var userArtists = DbContext.UserArtists.Include(x => x.Artist).Where(x => x.UserId == user.Id).ToArray() ?? new data.UserArtist[0];
|
||||
var userReleases = DbContext.UserReleases.Include(x => x.Release).Where(x => x.UserId == user.Id).ToArray() ?? new data.UserRelease[0];
|
||||
var userTracks = DbContext.UserTracks.Include(x => x.Track).Where(x => x.UserId == user.Id).ToArray() ?? new data.UserTrack[0];
|
||||
|
@ -631,7 +637,7 @@ namespace Roadie.Api.Services
|
|||
LastPlayedTrack = lastPlayedTrack == null
|
||||
? null
|
||||
: models.TrackList.FromDataTrack(
|
||||
MakeTrackPlayUrl(user, lastPlayedTrack.Id, lastPlayedTrack.RoadieId),
|
||||
MakeTrackPlayUrl(user, HttpContext.BaseUrl, lastPlayedTrack.Id, lastPlayedTrack.RoadieId),
|
||||
lastPlayedTrack,
|
||||
lastPlayedTrack.ReleaseMedia.MediaNumber,
|
||||
lastPlayedTrack.ReleaseMedia.Release,
|
||||
|
@ -658,7 +664,7 @@ namespace Roadie.Api.Services
|
|||
MostPlayedTrack = mostPlayedTrack == null
|
||||
? null
|
||||
: models.TrackList.FromDataTrack(
|
||||
MakeTrackPlayUrl(user, mostPlayedTrack.Id, mostPlayedTrack.RoadieId),
|
||||
MakeTrackPlayUrl(user, HttpContext.BaseUrl, mostPlayedTrack.Id, mostPlayedTrack.RoadieId),
|
||||
mostPlayedTrack,
|
||||
mostPlayedTrack.ReleaseMedia.MediaNumber,
|
||||
mostPlayedTrack.ReleaseMedia.Release,
|
||||
|
@ -682,8 +688,11 @@ namespace Roadie.Api.Services
|
|||
FavoritedTracks = userTracks.Where(x => x.IsFavorite ?? false).Count(),
|
||||
DislikedTracks = userTracks.Where(x => x.IsDisliked ?? false).Count()
|
||||
};
|
||||
tsw.Stop();
|
||||
timings.Add("stats", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
}
|
||||
Logger.LogInformation($"ByIdAction: User `{ user }`: includes [{includes.ToCSV()}], timings: [{ timings.ToTimings() }]");
|
||||
return Task.FromResult(new OperationResult<User>
|
||||
{
|
||||
IsSuccess = true,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"Roadie.Api": {
|
||||
"commandName": "Project",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Production"
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "http://localhost:5123/"
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue