Skip to content

Commit cec70d6

Browse files
committed
web app ui improvements
1 parent c5ca350 commit cec70d6

36 files changed

Lines changed: 294 additions & 442 deletions
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
using System.Text.Json;
2+
using Microsoft.Data.Sqlite;
3+
4+
static class AppData
5+
{
6+
public static readonly JsonSerializerOptions JsonOptions = new()
7+
{
8+
PropertyNameCaseInsensitive = true,
9+
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
10+
};
11+
12+
public static List<DatasetItem>? DatasetItems;
13+
public static byte[]? LargeJsonResponse;
14+
public static Dictionary<string, (byte[] Data, string ContentType)> StaticFiles = new();
15+
public static SqliteConnection? DbConnection;
16+
17+
public static void Load()
18+
{
19+
LoadDataset();
20+
LoadLargeDataset();
21+
LoadStaticFiles();
22+
OpenDatabase();
23+
}
24+
25+
static void LoadDataset()
26+
{
27+
var path = Environment.GetEnvironmentVariable("DATASET_PATH") ?? "/data/dataset.json";
28+
if (!File.Exists(path)) return;
29+
DatasetItems = JsonSerializer.Deserialize<List<DatasetItem>>(File.ReadAllText(path), JsonOptions);
30+
}
31+
32+
static void LoadLargeDataset()
33+
{
34+
var path = "/data/dataset-large.json";
35+
if (!File.Exists(path)) return;
36+
var items = JsonSerializer.Deserialize<List<DatasetItem>>(File.ReadAllText(path), JsonOptions);
37+
if (items == null) return;
38+
39+
var processed = new List<ProcessedItem>(items.Count);
40+
foreach (var item in items)
41+
{
42+
processed.Add(new ProcessedItem
43+
{
44+
Id = item.Id, Name = item.Name, Category = item.Category,
45+
Price = item.Price, Quantity = item.Quantity, Active = item.Active,
46+
Tags = item.Tags, Rating = item.Rating,
47+
Total = Math.Round(item.Price * item.Quantity, 2)
48+
});
49+
}
50+
LargeJsonResponse = JsonSerializer.SerializeToUtf8Bytes(
51+
new { items = processed, count = processed.Count }, JsonOptions);
52+
}
53+
54+
static void LoadStaticFiles()
55+
{
56+
var dir = "/data/static";
57+
if (!Directory.Exists(dir)) return;
58+
59+
var mimeTypes = new Dictionary<string, string>
60+
{
61+
{".css", "text/css"}, {".js", "application/javascript"}, {".html", "text/html"},
62+
{".woff2", "font/woff2"}, {".svg", "image/svg+xml"}, {".webp", "image/webp"}, {".json", "application/json"}
63+
};
64+
foreach (var file in Directory.GetFiles(dir))
65+
{
66+
var name = Path.GetFileName(file);
67+
var ext = Path.GetExtension(file);
68+
var ct = mimeTypes.GetValueOrDefault(ext, "application/octet-stream");
69+
StaticFiles[name] = (File.ReadAllBytes(file), ct);
70+
}
71+
}
72+
73+
static void OpenDatabase()
74+
{
75+
var path = "/data/benchmark.db";
76+
if (!File.Exists(path)) return;
77+
DbConnection = new SqliteConnection($"Data Source={path};Mode=ReadOnly");
78+
DbConnection.Open();
79+
using var pragma = DbConnection.CreateCommand();
80+
pragma.CommandText = "PRAGMA mmap_size=268435456";
81+
pragma.ExecuteNonQuery();
82+
}
83+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
using System.Text.Json;
2+
3+
static class Handlers
4+
{
5+
public static IResult GetBaseline(HttpRequest req)
6+
{
7+
return Results.Text(SumQuery(req).ToString());
8+
}
9+
10+
public static async Task<IResult> PostBaseline(HttpRequest req)
11+
{
12+
int sum = SumQuery(req);
13+
using var reader = new StreamReader(req.Body);
14+
var body = await reader.ReadToEndAsync();
15+
if (int.TryParse(body, out int b))
16+
sum += b;
17+
return Results.Text(sum.ToString());
18+
}
19+
20+
public static IResult GetBaseline2(HttpRequest req)
21+
{
22+
return Results.Text(SumQuery(req).ToString());
23+
}
24+
25+
public static IResult Pipeline()
26+
{
27+
return Results.Text("ok");
28+
}
29+
30+
public static async Task<IResult> Upload(HttpRequest req)
31+
{
32+
using var ms = new MemoryStream();
33+
await req.Body.CopyToAsync(ms);
34+
return Results.Text(ms.Length.ToString());
35+
}
36+
37+
public static IResult Json()
38+
{
39+
if (AppData.DatasetItems == null)
40+
return Results.Problem("Dataset not loaded");
41+
42+
var items = new List<ProcessedItem>(AppData.DatasetItems.Count);
43+
foreach (var item in AppData.DatasetItems)
44+
{
45+
items.Add(new ProcessedItem
46+
{
47+
Id = item.Id, Name = item.Name, Category = item.Category,
48+
Price = item.Price, Quantity = item.Quantity, Active = item.Active,
49+
Tags = item.Tags, Rating = item.Rating,
50+
Total = Math.Round(item.Price * item.Quantity, 2)
51+
});
52+
}
53+
return Results.Json(new { items, count = items.Count });
54+
}
55+
56+
public static async Task Compression(HttpContext ctx)
57+
{
58+
if (AppData.LargeJsonResponse == null)
59+
{
60+
ctx.Response.StatusCode = 500;
61+
return;
62+
}
63+
ctx.Response.ContentType = "application/json";
64+
await ctx.Response.Body.WriteAsync(AppData.LargeJsonResponse);
65+
}
66+
67+
public static IResult StaticFile(string filename)
68+
{
69+
if (AppData.StaticFiles.TryGetValue(filename, out var sf))
70+
return Results.Bytes(sf.Data, sf.ContentType);
71+
return Results.NotFound();
72+
}
73+
74+
public static IResult Database(HttpRequest req)
75+
{
76+
if (AppData.DbConnection == null)
77+
return Results.Problem("DB not available");
78+
79+
double min = 10, max = 50;
80+
if (req.Query.ContainsKey("min") && double.TryParse(req.Query["min"], out double pmin))
81+
min = pmin;
82+
if (req.Query.ContainsKey("max") && double.TryParse(req.Query["max"], out double pmax))
83+
max = pmax;
84+
85+
using var cmd = AppData.DbConnection.CreateCommand();
86+
cmd.CommandText = "SELECT id, name, category, price, quantity, active, tags, rating_score, rating_count FROM items WHERE price BETWEEN @min AND @max LIMIT 50";
87+
cmd.Parameters.AddWithValue("@min", min);
88+
cmd.Parameters.AddWithValue("@max", max);
89+
using var reader = cmd.ExecuteReader();
90+
91+
var items = new List<object>();
92+
while (reader.Read())
93+
{
94+
items.Add(new
95+
{
96+
id = reader.GetInt32(0),
97+
name = reader.GetString(1),
98+
category = reader.GetString(2),
99+
price = reader.GetDouble(3),
100+
quantity = reader.GetInt32(4),
101+
active = reader.GetInt32(5) == 1,
102+
tags = JsonSerializer.Deserialize<List<string>>(reader.GetString(6)),
103+
rating = new { score = reader.GetDouble(7), count = reader.GetInt32(8) },
104+
});
105+
}
106+
return Results.Json(new { items, count = items.Count });
107+
}
108+
109+
static int SumQuery(HttpRequest req)
110+
{
111+
int sum = 0;
112+
foreach (var (_, values) in req.Query)
113+
foreach (var v in values)
114+
if (int.TryParse(v, out int n)) sum += n;
115+
return sum;
116+
}
117+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
class DatasetItem
2+
{
3+
public int Id { get; set; }
4+
public string Name { get; set; } = "";
5+
public string Category { get; set; } = "";
6+
public double Price { get; set; }
7+
public int Quantity { get; set; }
8+
public bool Active { get; set; }
9+
public List<string> Tags { get; set; } = new();
10+
public RatingInfo Rating { get; set; } = new();
11+
}
12+
13+
class ProcessedItem
14+
{
15+
public int Id { get; set; }
16+
public string Name { get; set; } = "";
17+
public string Category { get; set; } = "";
18+
public double Price { get; set; }
19+
public int Quantity { get; set; }
20+
public bool Active { get; set; }
21+
public List<string> Tags { get; set; } = new();
22+
public RatingInfo Rating { get; set; } = new();
23+
public double Total { get; set; }
24+
}
25+
26+
class RatingInfo
27+
{
28+
public double Score { get; set; }
29+
public int Count { get; set; }
30+
}

0 commit comments

Comments
 (0)