Initial push
This commit is contained in:
158
samples/SampleWebApi/Controllers/AnalyticsController.cs
Normal file
158
samples/SampleWebApi/Controllers/AnalyticsController.cs
Normal file
@@ -0,0 +1,158 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SqrtSpace.SpaceTime.AspNetCore;
|
||||
using SqrtSpace.SpaceTime.Core;
|
||||
using SampleWebApi.Models;
|
||||
using SampleWebApi.Services;
|
||||
|
||||
namespace SampleWebApi.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class AnalyticsController : ControllerBase
|
||||
{
|
||||
private readonly IOrderAnalyticsService _analyticsService;
|
||||
private readonly ILogger<AnalyticsController> _logger;
|
||||
|
||||
public AnalyticsController(IOrderAnalyticsService analyticsService, ILogger<AnalyticsController> logger)
|
||||
{
|
||||
_analyticsService = analyticsService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate revenue by category using memory-efficient aggregation
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This endpoint demonstrates using external grouping for large datasets.
|
||||
/// When processing millions of orders, it automatically uses disk-based
|
||||
/// aggregation to stay within memory limits.
|
||||
/// </remarks>
|
||||
[HttpGet("revenue-by-category")]
|
||||
public async Task<ActionResult<IEnumerable<CategoryRevenue>>> GetRevenueByCategory(
|
||||
[FromQuery] DateTime? startDate = null,
|
||||
[FromQuery] DateTime? endDate = null)
|
||||
{
|
||||
var result = await _analyticsService.GetRevenueByCategoryAsync(startDate, endDate);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get top customers using external sorting
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This endpoint finds top customers by order value using external sorting.
|
||||
/// Even with millions of customers, it maintains O(√n) memory usage.
|
||||
/// </remarks>
|
||||
[HttpGet("top-customers")]
|
||||
public async Task<ActionResult<IEnumerable<CustomerSummary>>> GetTopCustomers(
|
||||
[FromQuery] int top = 100,
|
||||
[FromQuery] DateTime? since = null)
|
||||
{
|
||||
if (top > 1000)
|
||||
{
|
||||
return BadRequest("Cannot retrieve more than 1000 customers at once");
|
||||
}
|
||||
|
||||
var customers = await _analyticsService.GetTopCustomersAsync(top, since);
|
||||
return Ok(customers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stream real-time order analytics
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This endpoint streams analytics data in real-time using Server-Sent Events (SSE).
|
||||
/// It demonstrates memory-efficient streaming of continuous data.
|
||||
/// </remarks>
|
||||
[HttpGet("real-time/orders")]
|
||||
[SpaceTimeStreaming]
|
||||
public async Task StreamOrderAnalytics(CancellationToken cancellationToken)
|
||||
{
|
||||
Response.ContentType = "text/event-stream";
|
||||
Response.Headers.Append("Cache-Control", "no-cache");
|
||||
Response.Headers.Append("X-Accel-Buffering", "no");
|
||||
|
||||
await foreach (var analytics in _analyticsService.StreamRealTimeAnalyticsAsync(cancellationToken))
|
||||
{
|
||||
var data = System.Text.Json.JsonSerializer.Serialize(analytics);
|
||||
await Response.WriteAsync($"data: {data}\n\n", cancellationToken);
|
||||
await Response.Body.FlushAsync(cancellationToken);
|
||||
|
||||
// Small delay to simulate real-time updates
|
||||
await Task.Delay(1000, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate complex report with checkpointing
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This endpoint generates a complex report that may take a long time.
|
||||
/// It uses checkpointing to allow resuming if the operation is interrupted.
|
||||
/// The report includes multiple aggregations and can handle billions of records.
|
||||
/// </remarks>
|
||||
[HttpPost("reports/generate")]
|
||||
[EnableCheckpoint(Strategy = CheckpointStrategy.SqrtN)]
|
||||
public async Task<ActionResult<ReportResult>> GenerateReport(
|
||||
[FromBody] ReportRequest request,
|
||||
[FromHeader(Name = "X-Report-Id")] string? reportId = null)
|
||||
{
|
||||
reportId ??= Guid.NewGuid().ToString();
|
||||
|
||||
var checkpoint = HttpContext.Features.Get<ICheckpointFeature>();
|
||||
ReportState? previousState = null;
|
||||
|
||||
if (checkpoint != null)
|
||||
{
|
||||
previousState = await checkpoint.CheckpointManager.RestoreLatestCheckpointAsync<ReportState>();
|
||||
if (previousState != null)
|
||||
{
|
||||
_logger.LogInformation("Resuming report generation from checkpoint. Progress: {progress}%",
|
||||
previousState.ProgressPercent);
|
||||
}
|
||||
}
|
||||
|
||||
var result = await _analyticsService.GenerateComplexReportAsync(
|
||||
request,
|
||||
reportId,
|
||||
previousState,
|
||||
checkpoint?.CheckpointManager);
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Analyze order patterns using machine learning with batched processing
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This endpoint demonstrates processing large datasets for ML analysis
|
||||
/// using √n batching to maintain memory efficiency while computing features.
|
||||
/// </remarks>
|
||||
[HttpPost("analyze-patterns")]
|
||||
public async Task<ActionResult<PatternAnalysisResult>> AnalyzeOrderPatterns(
|
||||
[FromBody] PatternAnalysisRequest request)
|
||||
{
|
||||
if (request.MaxOrdersToAnalyze > 1_000_000)
|
||||
{
|
||||
return BadRequest("Cannot analyze more than 1 million orders in a single request");
|
||||
}
|
||||
|
||||
var result = await _analyticsService.AnalyzeOrderPatternsAsync(request);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get memory usage statistics for the analytics operations
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This endpoint provides insights into how SpaceTime is managing memory
|
||||
/// for analytics operations, useful for monitoring and optimization.
|
||||
/// </remarks>
|
||||
[HttpGet("memory-stats")]
|
||||
public ActionResult<MemoryStatistics> GetMemoryStatistics()
|
||||
{
|
||||
var stats = _analyticsService.GetMemoryStatistics();
|
||||
return Ok(stats);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user