diff --git a/src/BirdsiteLive.Twitter/CachedTwitterTweetService.cs b/src/BirdsiteLive.Twitter/CachedTwitterTweetService.cs
new file mode 100644
index 0000000..200df02
--- /dev/null
+++ b/src/BirdsiteLive.Twitter/CachedTwitterTweetService.cs
@@ -0,0 +1,63 @@
+using System;
+using BirdsiteLive.Twitter.Models;
+using Microsoft.Extensions.Caching.Memory;
+
+namespace BirdsiteLive.Twitter
+{
+ public interface ICachedTwitterTweetsService : ITwitterTweetsService
+ {
+ void PurgeTweet(long statusId);
+ }
+
+ public class CachedTwitterTweetsService : ICachedTwitterTweetsService
+ {
+ private readonly ITwitterTweetsService _twitterService;
+
+ private MemoryCache _tweetCache = new MemoryCache(new MemoryCacheOptions()
+ {
+ SizeLimit = 5000
+ });
+ private MemoryCacheEntryOptions _cacheEntryOptions = new MemoryCacheEntryOptions()
+ .SetSize(1)//Size amount
+ //Priority on removing when reaching size limit (memory pressure)
+ .SetPriority(CacheItemPriority.High)
+ // Keep in cache for this time, reset time if accessed.
+ // We set this lower than a user's in case they delete this Tweet for some reason; we don't need that cached.
+ .SetSlidingExpiration(TimeSpan.FromHours(2))
+ // Remove from cache after this time, regardless of sliding expiration
+ .SetAbsoluteExpiration(TimeSpan.FromDays(7));
+
+ #region Ctor
+ public CachedTwitterTweetsService(ITwitterTweetsService twitterService)
+ {
+ _twitterService = twitterService;
+ }
+
+ public ExtractedTweet[] GetTimeline(string username, int nberTweets, long fromTweetId = -1)
+ {
+ // This sounds like it'd be silly to cache; pass this directly to TwitterService.
+ // Theoretically this shouldn't be called more than once every 15 min anyway?
+ return _twitterService.GetTimeline(username, nberTweets, fromTweetId);
+ }
+
+ public ExtractedTweet GetTweet(long statusId)
+ {
+ if(!_tweetCache.TryGetValue(statusId, out ExtractedTweet tweet))
+ {
+ tweet = _twitterService.GetTweet(statusId);
+
+ // Unlike with the user cache, save the null value anyway to prevent (quicker) API exhaustion.
+ // It's incredibly unlikely that a tweet with this ID is going to magickally appear within 2 hours.
+ _tweetCache.Set(statusId, tweet, _cacheEntryOptions);
+ }
+
+ return tweet;
+ }
+ #endregion
+
+ public void PurgeTweet(long statusId)
+ {
+ _tweetCache.Remove(statusId);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/BirdsiteLive.Twitter/CachedTwitterService.cs b/src/BirdsiteLive.Twitter/CachedTwitterUserService.cs
similarity index 100%
rename from src/BirdsiteLive.Twitter/CachedTwitterService.cs
rename to src/BirdsiteLive.Twitter/CachedTwitterUserService.cs
diff --git a/src/BirdsiteLive/BirdsiteLive.csproj b/src/BirdsiteLive/BirdsiteLive.csproj
index dd17829..08b6809 100644
--- a/src/BirdsiteLive/BirdsiteLive.csproj
+++ b/src/BirdsiteLive/BirdsiteLive.csproj
@@ -11,6 +11,7 @@
+
diff --git a/src/BirdsiteLive/Controllers/UsersController.cs b/src/BirdsiteLive/Controllers/UsersController.cs
index a06b1e9..15e552e 100644
--- a/src/BirdsiteLive/Controllers/UsersController.cs
+++ b/src/BirdsiteLive/Controllers/UsersController.cs
@@ -143,6 +143,7 @@ namespace BirdsiteLive.Controllers
{
var succeeded = await _userService.FollowRequestedAsync(signature, r.Method, r.Path,
r.QueryString.ToString(), RequestHeaders(r.Headers), activity as ActivityFollow, body);
+
if (succeeded) return Accepted();
else return Unauthorized();
}
diff --git a/src/BirdsiteLive/Startup.cs b/src/BirdsiteLive/Startup.cs
index 16c7ee4..034d414 100644
--- a/src/BirdsiteLive/Startup.cs
+++ b/src/BirdsiteLive/Startup.cs
@@ -91,6 +91,9 @@ namespace BirdsiteLive
services.For().DecorateAllWith();
services.For().Use().Singleton();
+ services.For().DecorateAllWith();
+ services.For().Use().Singleton();
+
services.For().Use().Singleton();
services.Scan(_ =>
@@ -117,7 +120,8 @@ namespace BirdsiteLive
{
if (env.IsDevelopment())
{
- app.UseDeveloperExceptionPage();
+ app.UseDeveloperExceptionPage();
+ app.UseBrowserLink();
}
else
{