2
2
using OurUmbraco . Forum . Extensions ;
3
3
using OurUmbraco . Forum . Models ;
4
4
using System ;
5
- using System . Collections . Concurrent ;
6
5
using System . Collections . Generic ;
7
6
using System . Linq ;
8
7
using System . Net . Http ;
9
- using System . Runtime . Caching ;
10
- using System . Threading ;
11
- using System . Threading . Tasks ;
12
8
13
9
namespace OurUmbraco . Forum . Services
14
10
{
15
11
internal class DiscourseService
16
12
{
17
- internal async Task < DiscourseTopic > GetTopicByOldIdAsync ( int id )
13
+ internal DiscourseTopic GetTopicByOldIdAsync ( int id )
18
14
{
19
15
var handler = new HttpClientHandler
20
16
{
@@ -31,119 +27,71 @@ internal async Task<DiscourseTopic> GetTopicByOldIdAsync(int id)
31
27
client . DefaultRequestHeaders . Add ( "Api-Key" , $ "{ System . Configuration . ConfigurationManager . AppSettings [ "DiscourseApiKey" ] } ") ;
32
28
client . DefaultRequestHeaders . Add ( "Api-Username" , $ "{ System . Configuration . ConfigurationManager . AppSettings [ "DiscourseApiUsername" ] } ") ;
33
29
34
- var result = await client . GetAsync ( $ "t/external_id/{ id } .json") ;
30
+ var result = client . GetAsync ( $ "t/external_id/{ id } .json") . Result ;
35
31
36
32
if ( result . IsSuccessStatusCode == false )
37
33
{
38
34
return null ;
39
35
}
40
36
else
41
37
{
42
- var resultContent = await result . Content . ReadAsStringAsync ( ) ;
38
+ var resultContent = result . Content . ReadAsStringAsync ( ) . Result ;
43
39
var discourseTopic = JsonConvert . DeserializeObject < DiscourseTopic > ( resultContent ) ;
44
40
return discourseTopic ;
45
41
}
46
42
}
47
43
}
48
44
49
- internal async Task < List < DiscourseTopic > > GetLatestTopicsAsync ( string categorySlug , int categoryId )
45
+ internal List < DiscourseTopic > GetLatestTopics ( string categorySlug , int categoryId )
50
46
{
51
- var cacheKey = "LatestDiscourseTopics" + categorySlug + categoryId ;
52
47
53
- return await AsyncMemoryCache . GetOrAddAsync ( "myCacheKey" , async ( ) =>
54
- {
55
- var forumBaseUrl = System . Configuration . ConfigurationManager . AppSettings [ "DiscourseApiBaseUrl" ] ;
48
+ var cacheKey = "LatestDiscourseTopics" + categorySlug + categoryId ;
56
49
57
- using ( var client = new HttpClient ( ) )
50
+ return ( List < DiscourseTopic > ) Umbraco . Core . ApplicationContext . Current . ApplicationCache . RuntimeCache . GetCacheItem (
51
+ cacheKey ,
52
+ ( ) =>
58
53
{
59
- client . BaseAddress = new Uri ( forumBaseUrl ) ;
60
- client . DefaultRequestHeaders . Add ( "Api-Key" , $ "{ System . Configuration . ConfigurationManager . AppSettings [ "DiscourseApiKey" ] } ") ;
61
- client . DefaultRequestHeaders . Add ( "Api-Username" , $ "{ System . Configuration . ConfigurationManager . AppSettings [ "DiscourseApiUsername" ] } ") ;
54
+ var forumBaseUrl = System . Configuration . ConfigurationManager . AppSettings [ "DiscourseApiBaseUrl" ] ;
62
55
63
- var endPoint = $ "c/{ categorySlug } /{ categoryId } .json?order=created";
64
- var result = await client . GetAsync ( endPoint ) ;
65
- if ( ! result . IsSuccessStatusCode )
56
+ using ( var client = new HttpClient ( ) )
66
57
{
67
- var resultContent = await result . Content . ReadAsStringAsync ( ) ;
68
- var errorModel = JsonConvert . DeserializeObject < ErrorModel > ( resultContent ) ;
69
- string errors = string . Join ( ", ", errorModel . Errors ) ;
58
+ client . BaseAddress = new Uri ( forumBaseUrl ) ;
59
+ client . DefaultRequestHeaders . Add ( "Api-Key" , $ " { System . Configuration . ConfigurationManager . AppSettings [ "DiscourseApiKey" ] } " ) ;
60
+ client . DefaultRequestHeaders . Add ( "Api-Username ", $ " { System . Configuration . ConfigurationManager . AppSettings [ "DiscourseApiUsername" ] } " ) ;
70
61
71
- // Logger.Debug(typeof(DiscourseController), $"Listing latest topics from {endPoint} didn't succeed: {errors}");
62
+ var endPoint = $ "c/{ categorySlug } /{ categoryId } .json?order=created";
63
+ var result = client . GetAsync ( endPoint ) . Result ;
64
+ if ( result . IsSuccessStatusCode == false )
65
+ {
66
+ var resultContent = result . Content . ReadAsStringAsync ( ) . Result ;
67
+ var errorModel = JsonConvert . DeserializeObject < ErrorModel > ( resultContent ) ;
68
+ string errors = string . Join ( ", " , errorModel . Errors ) ;
72
69
73
- return null ;
74
- }
75
- else
76
- {
77
- var resultContent = await result . Content . ReadAsStringAsync ( ) ;
78
- var latestTopics = JsonConvert . DeserializeObject < TopicListModel > ( resultContent ) ;
79
- foreach ( var topic in latestTopics . TopicList . Topics )
70
+ //Logger.Debug(typeof(DiscourseController), $"Listing lastest topic from {endPoint} didn't succeeed: {errors}");
71
+
72
+ return null ;
73
+ }
74
+ else
80
75
{
81
- var latestPostUser = topic . LastPosterUsername ;
82
- var user = latestTopics . Users . FirstOrDefault ( x => x . Username == latestPostUser ) ;
83
- if ( user != null )
76
+ var resultContent = result . Content . ReadAsStringAsync ( ) . Result ;
77
+ var lastestTopics = JsonConvert . DeserializeObject < TopicListModel > ( resultContent ) ;
78
+ foreach ( var topic in lastestTopics . TopicList . Topics )
84
79
{
85
- topic . AuthorName = user . Name ;
86
- topic . AuthorAvatar = $ "{ forumBaseUrl } { user . AvatarTemplate . Replace ( "{size}" , "112" ) } ";
80
+ var latestPostUser = topic . LastPosterUsername ;
81
+ var user = lastestTopics . Users . FirstOrDefault ( x => x . Username == latestPostUser ) ;
82
+ if ( user != null )
83
+ {
84
+ topic . AuthorName = user . Name ;
85
+ topic . AuthorAvatar = $ "{ forumBaseUrl } { user . AvatarTemplate . Replace ( "{size}" , "112" ) } ";
86
+ }
87
+ topic . LastUpdatedFriendly = topic . LastPostedAt . ConvertToRelativeTime ( ) ;
88
+ topic . ForumCategory = "Umbraco questions" ;
87
89
}
88
- topic . LastUpdatedFriendly = topic . LastPostedAt . ConvertToRelativeTime ( ) ;
89
- topic . ForumCategory = "Umbraco questions" ;
90
- }
91
90
92
- return latestTopics . TopicList . Topics . OrderByDescending ( x => x . LastPostedAt ) . ToList ( ) ;
91
+ return lastestTopics . TopicList . Topics . OrderByDescending ( x => x . LastPostedAt ) . ToList ( ) ;
92
+ }
93
93
}
94
- }
95
- } , TimeSpan . FromMinutes ( 5 ) ) ;
94
+ } , TimeSpan . FromMinutes ( 5 ) ) ;
96
95
}
97
96
}
98
97
}
99
-
100
-
101
- public static class AsyncMemoryCache
102
- {
103
- private static readonly MemoryCache _cache = MemoryCache . Default ;
104
- private static readonly ConcurrentDictionary < string , SemaphoreSlim > _locks = new ConcurrentDictionary < string , SemaphoreSlim > ( ) ;
105
-
106
- public static async Task < T > GetOrAddAsync < T > ( string key , Func < Task < T > > valueFactory , TimeSpan absoluteExpiration )
107
- {
108
- if ( _cache . Contains ( key ) )
109
- {
110
- return ( T ) _cache . Get ( key ) ;
111
- }
112
-
113
- var semaphore = _locks . GetOrAdd ( key , _ => new SemaphoreSlim ( 1 , 1 ) ) ;
114
-
115
- try
116
- {
117
- await semaphore . WaitAsync ( ) ;
118
-
119
- // Double-check if the value was added while waiting for the lock
120
- if ( _cache . Contains ( key ) )
121
- {
122
- return ( T ) _cache . Get ( key ) ;
123
- }
124
-
125
- T result ;
126
- try
127
- {
128
- result = await valueFactory ( ) ;
129
- }
130
- catch ( Exception ex )
131
- {
132
- // Log the exception (optional)
133
- throw ; // Re-throw or handle as needed
134
- }
135
-
136
- if ( result != null )
137
- {
138
- _cache . Add ( key , result , DateTimeOffset . Now . Add ( absoluteExpiration ) ) ;
139
- }
140
-
141
- return result ;
142
- }
143
- finally
144
- {
145
- semaphore . Release ( ) ;
146
- _locks . TryRemove ( key , out _ ) ; // Clean up the lock
147
- }
148
- }
149
- }
0 commit comments