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.DatabaseHandler;
using Backend.ServiceHander; using Backend.ServiceHander;
using Backend.Interface;
using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);

View File

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

View File

@ -1,13 +1,14 @@
using Backend.DatabaseHandler; using Backend.DatabaseHandler;
using Backend.UserInterests; using Backend.ServiceHander;
using Backend.Interface;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
namespace Backend.Controllers; namespace Backend.Controllers
[ApiController]
[Route("api/user-interest")]
public sealed class UserInterestController : ControllerBase
{ {
[ApiController]
[Route("api/user-interest")]
public sealed class UserInterestController : ControllerBase
{
private readonly IUserInterestStore _store; private readonly IUserInterestStore _store;
public UserInterestController(IUserInterestStore store) public UserInterestController(IUserInterestStore store)
@ -63,4 +64,5 @@ public sealed class UserInterestController : ControllerBase
return BadRequest(ex.Message); 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.MarketDataRequest;
using Backend.Interface;
using Npgsql; using Npgsql;
namespace Backend.DatabaseHandler namespace Backend.DatabaseHandler

View File

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

View File

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

View File

@ -1,5 +1,6 @@
using Backend.DatabaseHandler; using Backend.DatabaseHandler;
using Backend.MarketDataRequest; using Backend.MarketDataRequest;
using Backend.Interface;
using IBApi; using IBApi;
using System.Globalization; 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; }
}