Skip to content

Instantly share code, notes, and snippets.

@neon-sunset
Last active July 1, 2023 14:35
Show Gist options
  • Select an option

  • Save neon-sunset/767cb0693c3ff222f78b236c9904a3fc to your computer and use it in GitHub Desktop.

Select an option

Save neon-sunset/767cb0693c3ff222f78b236c9904a3fc to your computer and use it in GitHub Desktop.
#pragma warning disable IL2026
using FastCache;
using Markdig;
using Microsoft.AspNetCore.Mvc;
using NonBlocking;
var builder = WebApplication.CreateBuilder();
builder.Services.AddHttpClient();
var app = builder.Build();
var stampedeGuard = new ConcurrentDictionary<string, SemaphoreSlim>();
app.MapGet("weather", async (
[FromQuery] string city,
[FromServices] HttpClient http) =>
{
Begin:
if (Cached<IResult>.TryGet("/weather", city, out var cached))
{
return cached.Value;
}
var queryLock = stampedeGuard.GetOrAdd(city, static _ => new SemaphoreSlim(1, 1));
if (!queryLock.Wait(0))
{
// Wait for the first in-flight request to complete then retry
await queryLock.WaitAsync();
queryLock.Release();
goto Begin;
}
var query = $"https://wttr.in/{city}";
var weather = await http.GetStringAsync(query);
var result = cached
.Save(Results.Content(weather, "text/html"), TimeSpan.FromMinutes(10), limit: 1000);
queryLock.Release();
return result;
});
app.MapGet("/posts/{postName}", static async (
[FromRoute] string postName) =>
{
if (Cached<IResult>.TryGet("posts", postName, out var cached))
{
return cached.Value;
}
var text = await File.ReadAllTextAsync($"posts/{postName}.md");
var html = Markdown.ToHtml(text);
var result = Results.Content(html, "text/html");
return cached.Save(result, TimeSpan.FromMinutes(30), limit: 100);
});
await app.RunAsync();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment