-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCachedHOSApi.cs
114 lines (102 loc) · 4.36 KB
/
CachedHOSApi.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
using Api.HOS.Json;
using Global.Util;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Channel = Api.HOS.Json.Channel;
#pragma warning disable CS1998
namespace Api.HOS
{
public class CachedHOSApi
{
private static readonly Dictionary<int, ChannelProgram[]> channelPrograms = new Dictionary<int, ChannelProgram[]>();
private static readonly Dictionary<int, AsyncLazy<ProgramAlbum[]>> programTracks = new Dictionary<int, AsyncLazy<ProgramAlbum[]>>();
private static readonly Dictionary<int, AsyncLazy<Track[]>> albumTracks = new Dictionary<int, AsyncLazy<Track[]>>();
// ugly code, hard to clean without macros
private static readonly AsyncLazy<Album[]> albumsLazy = new AsyncLazy<Album[]>(() => Task.Run(async () =>
{
return (await HOSApi.GetAlbumsAsync()).Select(album =>
{
albumTracks.TryAdd(album.id, new AsyncLazy<Track[]>(
() => HOSApi.GetAlbumTracksAsync(album.id)
));
return album;
}).ToArray();
}));
private static readonly AsyncLazy<Channel[]> channelsLazy = new AsyncLazy<Channel[]>(() => Task.Run(async () =>
{
return (await HOSApi.GetChannelsAsync()).Select(channel =>
{
channelPrograms.TryAdd(channel.id, channel.programs);
foreach (var program in channel.programs)
{
programTracks.TryAdd(program.id, new AsyncLazy<ProgramAlbum[]>(() => Task.Run(async () =>
{
return await HOSApi.GetProgramTracksAsync(program.id);
})));
}
return channel;
}).ToArray();
}));
public static async Task<Track> GetAlbumTrackById(int id)
{
return albumTracks.Values.Where(lazy => lazy.ValueCreated)
.SelectMany(lazy => lazy.GetAsync().BlockOn())
.FirstOrDefault(track => track.id == id);
}
public static async Task<Track> GetProgramTrackById(int id)
{
return programTracks.Values.Where(lazy => lazy.ValueCreated)
.SelectMany(lazy => lazy.GetAsync().BlockOn())
.SelectMany(programAlbum => programAlbum.tracks)
.FirstOrDefault(track => track.id == id);
}
public static async Task<Album[]> GetAlbumsAsync() => await albumsLazy.GetAsync();
public static async Task<Album[]> GetAlbumsAsync(IEnumerable<int> albumIds)
{
return (await GetAlbumsAsync()).Where(a => albumIds.Contains(a.id))
.ToArray();
}
public static async Task<Channel[]> GetChannelsAsync() => await channelsLazy.GetAsync();
public static async Task<Track[]> GetAlbumTracksAsync(int albumId)
{
try
{
return await albumTracks[albumId].GetAsync();
}
catch
{
if (!albumsLazy.ValueCreated)
{
await albumsLazy.GetAsync();
return await GetAlbumTracksAsync(albumId);
}
throw;
}
}
public static async Task<ProgramAlbum[]> GetProgramTracksAsync(int programId)
{
try
{
return await programTracks[programId].GetAsync();
}
catch
{
if (!channelsLazy.ValueCreated)
{
await channelsLazy.GetAsync();
return await GetProgramTracksAsync(programId);
}
throw;
}
}
// async function even though it's not needed; there to have an uniform api
public static async Task<ChannelProgram[]> GetChannelProgramsAsync(int channelId) => channelPrograms[channelId];
public static async Task<ChannelProgram[]> GetChannelProgramsAsync(IEnumerable<int> programIds)
{
return channelPrograms.Values.SelectMany(cp => cp)
.Where(cp => programIds.Contains(cp.id))
.ToArray();
}
}
}