Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
ea5656d
Added basic controller, logger, and db
devidnyk Oct 3, 2025
89538b1
Updated controller to refresh in another task
devidnyk Oct 4, 2025
73732af
Configure Program.cs with necessary middleware and services and Updat…
Oct 11, 2025
8e5f391
Added Client side code
Oct 11, 2025
3fd765a
Merge pull request #4 from devidnyk/user/swoyam/ChangedBackendForAPIC…
devidnyk Oct 11, 2025
b23445f
Merge pull request #5 from devidnyk/user/swoyam/AddedClientSideCode
devidnyk Oct 11, 2025
316f30a
Added single problem page and docker basics
devidnyk Oct 11, 2025
1a4d7e8
Fixing Links and Updated CSS
Oct 11, 2025
2898cfa
implemented pagination
Oct 11, 2025
872af20
Merge pull request #6 from devidnyk/user/swoyam/ClientUpdateVersion2
devidnyk Oct 11, 2025
5b5f369
allowed all origins
devidnyk Oct 11, 2025
4f81dba
Added search engine and removed keys
devidnyk Oct 11, 2025
07c38bb
Added AI Engine to label job category
devidnyk Oct 11, 2025
f5a811a
search query on previous days
devidnyk Oct 12, 2025
2531fd0
Removed Filter logic from client side
Oct 12, 2025
9f5a6d8
List implementation
Oct 12, 2025
7a9995c
Fixed List CSS
Oct 12, 2025
422c2a4
Merge pull request #7 from devidnyk/user/swoyam/FixPaginationWithFilters
devidnyk Oct 12, 2025
ca01a21
Added tag filtering
devidnyk Oct 12, 2025
997c8fb
Refactoring Solution
ayush777-hub Oct 16, 2025
d50def7
Adding milestones
ayush777-hub Oct 16, 2025
0477934
Merge pull request #9 from devidnyk/user/ayushbehera/CleanUpJobsBackend
devidnyk Oct 16, 2025
231ff53
Merge branch 'master' into users/devi/jobs-backend
devidnyk Oct 17, 2025
dd1427d
merged master and resolved conflicts
devidnyk Oct 17, 2025
efb9d23
UI Fixes for minimalistic compact design
Oct 18, 2025
22570a2
Added acustom hook to handle the storing and fetching from localstore
Oct 18, 2025
076c076
Added Clear solved button to reset localStore
Oct 18, 2025
34180d6
Merge pull request #10 from devidnyk/user/swoyam/UiFixAndCheckBoxImpl…
swoyamsss Oct 18, 2025
07581e4
Add scrapper configurations and isolated scrapping process
devidnyk Oct 18, 2025
0ccdbd7
Added shuffle in query params
devidnyk Oct 18, 2025
924ef71
Added configurable backend endpoint
devidnyk Oct 18, 2025
014a8ee
Added Shuffle functionality
Oct 18, 2025
62f5996
Merge pull request #11 from devidnyk/user/swoyam/AddedShuffleFunction…
swoyamsss Oct 18, 2025
b733e45
Refactoring code for async data pulls
ayush777-hub Oct 19, 2025
ac5c057
Merge pull request #12 from devidnyk/user/ayushbehera/AsyncProcessor
devidnyk Oct 25, 2025
8107cf7
Added basic background process controller and added basic scrapper
devidnyk Oct 25, 2025
111af8a
iMerge branch 'master' into users/devi/jobs-backend
devidnyk Oct 25, 2025
e9d8f22
Merge pull request #8 from devidnyk/users/devi/jobs-backend
devidnyk Oct 25, 2025
2ce4ff4
Fixed bug and added more info for tracking
devidnyk Oct 26, 2025
ba0dcd6
Merge pull request #13 from devidnyk/users/devi/jobs-backend
devidnyk Oct 26, 2025
c0b6fed
Updated JobDetails, added more query, and adeed problems metadata
devidnyk Oct 28, 2025
560da59
Merge pull request #14 from devidnyk/users/devi/jobs-backend
devidnyk Oct 28, 2025
9b18598
updated be endpoint
devidnyk Oct 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Updated controller to refresh in another task
  • Loading branch information
devidnyk committed Oct 4, 2025
commit 89538b1d10824bc924d569f7caee5a23b8fb6e2e
10 changes: 9 additions & 1 deletion src/Backend/Controllers/ProblemsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ public ProblemsController(AppContext appContext, ILogger<ProblemsController> log
this.configuration = configuration;
}

[HttpGet]
[Route("")]
public ActionResult<string> GetHome()
{
return Ok("Leetcode Wrapper Backend is running.");
}

[HttpGet]
[Route("problems")]
public async Task<ActionResult<ProblemPublicModel>> GetProblems(
Expand All @@ -36,7 +43,8 @@ public async Task<ActionResult<ProblemPublicModel>> GetProblems(
[Route("problems/{id}")]
public async Task<ActionResult<ProblemPublicModel>> GetProblems(string id)
{
if (appContext.dataProvider.problemsCache.TryGetValue(id, out var problem))
var problem = await appContext.dataProvider.GetProblemByIdAsync(id);
if (problem != null)
{
return Ok(problem);
}
Expand Down
81 changes: 60 additions & 21 deletions src/Backend/Operations/DataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,20 @@ namespace Backend.Operations

public class DataProvider
{
private const int RefreshIntervalInHours = 6;
private const int RefreshIntervalInHours = 3;
private CosmosClient cosmosClient;
private readonly IConfiguration configuration;
ILogger<DataProvider> logger;
private DateTime lastLoadedTime = DateTime.MinValue;
public Dictionary<string, Problem> problemsCache { get; private set; } = new Dictionary<string, Problem>(StringComparer.OrdinalIgnoreCase);
private Task backgroundRefreshTask;
private Dictionary<string, Problem> problemsCache = new Dictionary<string, Problem>(StringComparer.OrdinalIgnoreCase);

public DataProvider(CosmosClient client, IConfiguration configuration, ILogger<DataProvider> logger)
{
this.cosmosClient = client;
this.configuration = configuration;
this.logger = logger;
this.backgroundRefreshTask = Task.Run(() => this.StartBackgroundRefreshAsync(CancellationToken.None));
}

public async Task<List<Problem>> GetProblemsAsync(IFilter? filter = null)
Expand All @@ -28,43 +30,80 @@ public async Task<List<Problem>> GetProblemsAsync(IFilter? filter = null)
}
return allProblems.Values.ToList();
}

public async Task<Problem?> GetProblemByIdAsync(string id)
{
var allProblems = await GetAllProblemsAsync();
if (allProblems.TryGetValue(id, out var problem))
{
return problem;
}
return null;
}

private async Task<Dictionary<string, Problem>> GetAllProblemsAsync()
{
if ((DateTime.UtcNow - lastLoadedTime) > TimeSpan.FromHours(RefreshIntervalInHours))
if (problemsCache.Count == 0)
{
await LoadLatestDataAsync();
if (problemsCache.Count == 0)
{
this.logger.LogWarning("No problems found in the cache after loading data.");
}
}
return problemsCache;
}

private async Task LoadLatestDataAsync()
{
try
int maxRetries = 3;
for(int i = 0; i < maxRetries; i++)
{
var dbId = configuration.GetValue<string>("ApplicationSettings:CosmosDbDatabaseId");
var containerId = configuration.GetValue<string>("ApplicationSettings:CosmosDbContainerId");
var db = cosmosClient.GetDatabase(dbId);
var container = db.GetContainer(containerId);
try
{
var dbId = configuration.GetValue<string>("ApplicationSettings:CosmosDbDatabaseId");
var containerId = configuration.GetValue<string>("ApplicationSettings:CosmosDbContainerId");
var db = cosmosClient.GetDatabase(dbId);
var container = db.GetContainer(containerId);

var query = "SELECT * FROM c";
var queryDefinition = new QueryDefinition(query);
var queryResultSetIterator = container.GetItemQueryIterator<ProblemSchema>(queryDefinition);

var query = "SELECT * FROM c";
var queryDefinition = new QueryDefinition(query);
var queryResultSetIterator = container.GetItemQueryIterator<ProblemSchema>(queryDefinition);
List<Problem> results = new List<Problem>();
while (queryResultSetIterator.HasMoreResults)
{
var response = await queryResultSetIterator.ReadNextAsync();
results.AddRange(response.Select(item => new Problem(item)));
}

List<Problem> results = new List<Problem>();
while (queryResultSetIterator.HasMoreResults)
lastLoadedTime = DateTime.UtcNow;
problemsCache = results.ToDictionary(p => p.id, StringComparer.OrdinalIgnoreCase);
this.logger.LogInformation($"Loaded {problemsCache.Count} problems from Cosmos DB at {lastLoadedTime}");
break;
}
catch (Exception ex)
{
var response = await queryResultSetIterator.ReadNextAsync();
results.AddRange(response.Select(item => new Problem(item)));
this.logger.LogError($"Error loading data from Cosmos DB. {ex}");
await Task.Delay(TimeSpan.FromSeconds(2 * (i + 1)));
}

lastLoadedTime = DateTime.UtcNow;
problemsCache = results.ToDictionary(p => p.id, StringComparer.OrdinalIgnoreCase);
this.logger.LogInformation($"Loaded {problemsCache.Count} problems from Cosmos DB at {lastLoadedTime}");
}
catch (Exception ex)
}

public async Task StartBackgroundRefreshAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
this.logger.LogError($"Error loading data from Cosmos DB. {ex}");
try
{
await LoadLatestDataAsync();
}
catch (Exception ex)
{
this.logger.LogError($"Error during background data refresh: {ex}");
}

await Task.Delay(TimeSpan.FromHours(RefreshIntervalInHours), cancellationToken);
}
}
}
Expand Down