Restructured project.

This commit is contained in:
caspar 2026-03-19 05:14:27 -04:00
parent 54777c0a2d
commit 9c8d563aef
12 changed files with 96 additions and 84 deletions

View File

@ -1,5 +1,6 @@
using Backend.DatabaseHandler;
using Backend.ServiceHander;
using Backend.Interface;
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);

View File

@ -2,7 +2,7 @@ using Backend.ServiceHander;
using Backend.MarketDataRequest;
using Microsoft.AspNetCore.Mvc;
namespace BackendApi.Controller
namespace Backend.Controller
{
[ApiController]
[Route("api/market")]

View File

@ -1,66 +1,68 @@
using Backend.DatabaseHandler;
using Backend.UserInterests;
using Backend.ServiceHander;
using Backend.Interface;
using Microsoft.AspNetCore.Mvc;
namespace Backend.Controllers;
[ApiController]
[Route("api/user-interest")]
public sealed class UserInterestController : ControllerBase
namespace Backend.Controllers
{
private readonly IUserInterestStore _store;
public UserInterestController(IUserInterestStore store)
[ApiController]
[Route("api/user-interest")]
public sealed class UserInterestController : ControllerBase
{
_store = store;
}
private readonly IUserInterestStore _store;
[HttpGet("fetch")]
public async Task<ActionResult<UserInterestFetchResponse>> FetchAll(
[FromQuery] string user,
[FromQuery] string type)
{
try
public UserInterestController(IUserInterestStore store)
{
List<string> items = await _store.FetchAllAsync(user, type);
return Ok(new UserInterestFetchResponse
_store = store;
}
[HttpGet("fetch")]
public async Task<ActionResult<UserInterestFetchResponse>> FetchAll(
[FromQuery] string user,
[FromQuery] string type)
{
try
{
Items = items
});
List<string> items = await _store.FetchAllAsync(user, type);
return Ok(new UserInterestFetchResponse
{
Items = items
});
}
catch (ArgumentException ex)
{
return BadRequest(ex.Message);
}
}
catch (ArgumentException ex)
{
return BadRequest(ex.Message);
}
}
[HttpPost("add")]
public async Task<ActionResult<BoolResponse>> Add(
[FromBody] UserInterestModifyRequest request)
{
try
[HttpPost("add")]
public async Task<ActionResult<BoolResponse>> Add(
[FromBody] UserInterestModifyRequest request)
{
bool success = await _store.AddAsync(request.User, request.Type, request.Value);
return Ok(new BoolResponse { Success = success });
try
{
bool success = await _store.AddAsync(request.User, request.Type, request.Value);
return Ok(new BoolResponse { Success = success });
}
catch (ArgumentException ex)
{
return BadRequest(ex.Message);
}
}
catch (ArgumentException ex)
{
return BadRequest(ex.Message);
}
}
[HttpDelete("remove")]
public async Task<ActionResult<BoolResponse>> Remove(
[FromBody] UserInterestModifyRequest request)
{
try
[HttpDelete("remove")]
public async Task<ActionResult<BoolResponse>> Remove(
[FromBody] UserInterestModifyRequest request)
{
bool success = await _store.RemoveAsync(request.User, request.Type, request.Value);
return Ok(new BoolResponse { Success = success });
}
catch (ArgumentException ex)
{
return BadRequest(ex.Message);
try
{
bool success = await _store.RemoveAsync(request.User, request.Type, request.Value);
return Ok(new BoolResponse { Success = success });
}
catch (ArgumentException ex)
{
return BadRequest(ex.Message);
}
}
}
}

View File

@ -1,8 +0,0 @@
namespace Backend.DatabaseHandler;
public interface IUserInterestStore
{
Task<List<string>> FetchAllAsync(string user, string type);
Task<bool> AddAsync(string user, string type, string value);
Task<bool> RemoveAsync(string user, string type, string value);
}

View File

@ -1,4 +1,5 @@
using Backend.MarketDataRequest;
using Backend.Interface;
using Npgsql;
namespace Backend.DatabaseHandler

View File

@ -1,4 +1,5 @@
using Npgsql;
using Backend.Interface;
namespace Backend.DatabaseHandler;

View File

@ -1,6 +1,7 @@
using Backend.MarketDataRequest;
using Backend.DatabaseHandler;
namespace Backend.DatabaseHandler
namespace Backend.Interface
{
public interface IHistoricalMarketDataCache
{

View File

@ -0,0 +1,9 @@
namespace Backend.Interface
{
public interface IUserInterestStore
{
Task<List<string>> FetchAllAsync(string user, string type);
Task<bool> AddAsync(string user, string type, string value);
Task<bool> RemoveAsync(string user, string type, string value);
}
}

View File

@ -25,7 +25,7 @@ namespace Backend.MarketDataRequest
private readonly ConcurrentDictionary<int, LiveEquitySnapshot> _liveSnapshotsByRequest = new();
private readonly ConcurrentDictionary<int, TaskCompletionSource<LiveEquitySnapshot>> _liveRequests = new();
//Fundamentals data
// Fundamentals data
private readonly ConcurrentDictionary<int, FundamentalsEquitySnapshot> _fundamentalsSnapshotsByRequest = new();
private readonly ConcurrentDictionary<int, TaskCompletionSource<FundamentalsEquitySnapshot>> _fundamentalsRequests = new();
@ -131,6 +131,7 @@ namespace Backend.MarketDataRequest
Console.WriteLine($"[error] id={id}, code={errorCode}, time={errorTime}, msg={errorMsg}");
// Live requests
if (id > 0 && _liveRequests.TryRemove(id, out var liveTcs))
{
Client.cancelMktData(id);
@ -141,6 +142,7 @@ namespace Backend.MarketDataRequest
return;
}
// Historical requests
if (id > 0 && _historyRequests.TryRemove(id, out var historyTcs))
{
_BarsByRequest.TryRemove(id, out _);
@ -150,6 +152,7 @@ namespace Backend.MarketDataRequest
return;
}
// Fundamentals
if (id > 0 && _fundamentalsRequests.TryRemove(id, out var fundamentalsTcs))
{
Client.cancelMktData(id);

View File

@ -1,5 +1,6 @@
using Backend.DatabaseHandler;
using Backend.MarketDataRequest;
using Backend.Interface;
using IBApi;
using System.Globalization;

View File

@ -0,0 +1,25 @@
namespace Backend.ServiceHander
{
public sealed class UserInterestFetchRequest
{
public string User { get; set; } = string.Empty;
public string Type { get; set; } = string.Empty; // "symbol" or "topic"
}
public sealed class UserInterestModifyRequest
{
public string User { get; set; } = string.Empty;
public string Type { get; set; } = string.Empty; // "symbol" or "topic"
public string Value { get; set; } = string.Empty; // symbol or topic
}
public sealed class UserInterestFetchResponse
{
public List<string> Items { get; set; } = new();
}
public sealed class BoolResponse
{
public bool Success { get; set; }
}
}

View File

@ -1,24 +0,0 @@
namespace Backend.UserInterests;
public sealed class UserInterestFetchRequest
{
public string User { get; set; } = string.Empty;
public string Type { get; set; } = string.Empty; // "symbol" or "topic"
}
public sealed class UserInterestModifyRequest
{
public string User { get; set; } = string.Empty;
public string Type { get; set; } = string.Empty; // "symbol" or "topic"
public string Value { get; set; } = string.Empty; // symbol or topic
}
public sealed class UserInterestFetchResponse
{
public List<string> Items { get; set; } = new();
}
public sealed class BoolResponse
{
public bool Success { get; set; }
}