diff --git a/AAIntegration.SimmonsBank.API/AAIntegration.SimmonsBank.API.csproj b/AAIntegration.SimmonsBank.API/AAIntegration.SimmonsBank.API.csproj
index 6e5f1ae..9617359 100644
--- a/AAIntegration.SimmonsBank.API/AAIntegration.SimmonsBank.API.csproj
+++ b/AAIntegration.SimmonsBank.API/AAIntegration.SimmonsBank.API.csproj
@@ -30,6 +30,7 @@
+
diff --git a/AAIntegration.SimmonsBank.API/Configs/EnvelopeFundConfig.cs b/AAIntegration.SimmonsBank.API/Configs/EnvelopeFundConfig.cs
deleted file mode 100644
index 7fb0dd5..0000000
--- a/AAIntegration.SimmonsBank.API/Configs/EnvelopeFundConfig.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace AAIntegration.SimmonsBank.API.Configs;
-
-public class EnvelopeFundConfig
-{
- public int CheckIntervalInMinutes { get; set; }
-}
diff --git a/AAIntegration.SimmonsBank.API/Configs/PuppeteerConfig.cs b/AAIntegration.SimmonsBank.API/Configs/PuppeteerConfig.cs
new file mode 100644
index 0000000..907eaea
--- /dev/null
+++ b/AAIntegration.SimmonsBank.API/Configs/PuppeteerConfig.cs
@@ -0,0 +1,15 @@
+namespace AAIntegration.SimmonsBank.API.Configs;
+
+public class PuppeteerConfig
+{
+ public int KeepAliveIntervalMinutes { get; set; }
+ public int CheckForNewDataIntervalMinutes { get; set; }
+ public int TaskCheckIntervalMinutes { get; set; }
+}
+
+public class PuppeteerConfigConstants
+{
+ public const string KeepAliveIntervalMinutes = "KeepAliveIntervalMinutes";
+ public const string CheckForNewDataIntervalMinutes = "CheckForNewDataIntervalMinutes";
+ public const string TaskCheckIntervalMinutes = "TaskCheckIntervalMinutes";
+}
\ No newline at end of file
diff --git a/AAIntegration.SimmonsBank.API/Models/Accounts/AccountCreateRequest.cs b/AAIntegration.SimmonsBank.API/Models/Accounts/AccountCreateRequest.cs
index 24cc71e..71f4285 100644
--- a/AAIntegration.SimmonsBank.API/Models/Accounts/AccountCreateRequest.cs
+++ b/AAIntegration.SimmonsBank.API/Models/Accounts/AccountCreateRequest.cs
@@ -10,5 +10,4 @@ public class AccountCreateRequest
public string InitialBalance { get; set; }
public int Currency { get; set; }
public string ExternalAccountNumber { get; set; }
- public int Owner { get; set; }
}
\ No newline at end of file
diff --git a/AAIntegration.SimmonsBank.API/Processes/IPuppeteerProcess.cs b/AAIntegration.SimmonsBank.API/Processes/IPuppeteerProcess.cs
index 9d3ad5e..714f270 100644
--- a/AAIntegration.SimmonsBank.API/Processes/IPuppeteerProcess.cs
+++ b/AAIntegration.SimmonsBank.API/Processes/IPuppeteerProcess.cs
@@ -1,9 +1,10 @@
using System.Threading.Tasks;
+using AAIntegration.SimmonsBank.API.Entities;
using AAIntegration.SimmonsBank.API.Services;
namespace AAIntegration.SimmonsBank.API.Processes;
public interface IPuppeteerProcess
{
- Task FundEnvelopes();
+ Task StayLoggedIn(User user);
}
diff --git a/AAIntegration.SimmonsBank.API/Processes/PuppeteerProcess.cs b/AAIntegration.SimmonsBank.API/Processes/PuppeteerProcess.cs
index f424249..e00ed65 100644
--- a/AAIntegration.SimmonsBank.API/Processes/PuppeteerProcess.cs
+++ b/AAIntegration.SimmonsBank.API/Processes/PuppeteerProcess.cs
@@ -6,48 +6,33 @@ using AAIntegration.SimmonsBank.API.Entities;
using AAIntegration.SimmonsBank.API.Models.Transactions;
using AAIntegration.SimmonsBank.API.Services;
using Internal;
+using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
namespace AAIntegration.SimmonsBank.API.Processes;
public class PuppeteerProcess : IPuppeteerProcess
{
- private readonly EnvelopeFundConfig _config;
+ private readonly PuppeteerConfig _config;
private readonly ILogger _logger;
+ private readonly IMemoryCache _memoryCache;
public PuppeteerProcess(
- IOptions config,
- ILogger logger)
+ IOptions config,
+ ILogger logger,
+ IMemoryCache memoryCache)
{
- _config = config.Value;
- _logger = logger;
+ _config = config.Value;
+ _logger = logger;
+ _memoryCache = memoryCache;
}
- public async Task FundEnvelopes()
- {
- _logger.LogInformation($"Starting envelope funding...");
-
- // Grab envelopes
- /*List envelopes = envelopeService.GetAll().ToList();
+ public async Task StayLoggedIn(User user)
+ {
+ _logger.LogInformation($"... doing work and processing for user {user.Id} ...");
+ }
- bool anyTriggered = false;
-
- foreach (Envelope env in envelopes)
- {
- // Check if needs triggering
- if (env.Enabled && !envelopeService.HasBeenFundedThisMonth(env.Id))
- {
- _logger.LogInformation($"Envelope '{env.Name}' (id={env.Id}) needs funding - Has now been triggered.");
- anyTriggered = true;
+ // Helper Functions
- // Fund Envelope
- envelopeService.FundEnvelopeForThisMonth(env.Id);
- }
- }*/
-
- if (false)
- _logger.LogInformation($"No action taken.");
- else
- _logger.LogInformation($"Envelope funding complete.");
- }
+
}
diff --git a/AAIntegration.SimmonsBank.API/Program.cs b/AAIntegration.SimmonsBank.API/Program.cs
index 450ebfd..b3da98b 100644
--- a/AAIntegration.SimmonsBank.API/Program.cs
+++ b/AAIntegration.SimmonsBank.API/Program.cs
@@ -70,7 +70,7 @@ internal class Program
// Configure strongly typed settings object
builder.Services.Configure(builder.Configuration.GetSection("AppSettings"));
- builder.Services.Configure(builder.Configuration.GetSection("EnvelopeFund"));
+ builder.Services.Configure(builder.Configuration.GetSection("Puppeteer"));
builder.Services.Configure(builder.Configuration.GetSection("ActiveAllocator:Database"));
DatabaseConfig dbConfig = builder.Configuration.GetSection("ActiveAllocator:Database").Get();
diff --git a/AAIntegration.SimmonsBank.API/Services/UserService.cs b/AAIntegration.SimmonsBank.API/Services/UserService.cs
index 16d0774..3039985 100644
--- a/AAIntegration.SimmonsBank.API/Services/UserService.cs
+++ b/AAIntegration.SimmonsBank.API/Services/UserService.cs
@@ -24,6 +24,7 @@ public interface IUserService
void Delete(string apiKey);
Dictionary GetAllApiKeys();
User GetUser(string ApiKey);
+ IEnumerable GetAll();
/* Other cringe way
AuthenticateResponse Authenticate(AuthenticateRequest model);
@@ -116,6 +117,11 @@ public class UserService : IUserService
return user;
}
+ public IEnumerable GetAll()
+ {
+ return _context.Users;
+ }
+
// helper methods
private User getUser(int id)
diff --git a/AAIntegration.SimmonsBank.API/Workers/PuppeteerWorker.cs b/AAIntegration.SimmonsBank.API/Workers/PuppeteerWorker.cs
index c84f5cd..9017a00 100644
--- a/AAIntegration.SimmonsBank.API/Workers/PuppeteerWorker.cs
+++ b/AAIntegration.SimmonsBank.API/Workers/PuppeteerWorker.cs
@@ -4,50 +4,136 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using AAIntegration.SimmonsBank.API.Processes;
using AAIntegration.SimmonsBank.API.Services;
+using AAIntegration.SimmonsBank.API.Entities;
+using Microsoft.Extensions.Caching.Memory;
namespace AAIntegration.SimmonsBank.API.Workers;
public class PuppeteerWorker : BackgroundService
{
- private readonly EnvelopeFundConfig _config;
+ private readonly PuppeteerConfig _config;
private readonly IPuppeteerProcess _puppeteerProcess;
private readonly ILogger _logger;
+ private readonly IMemoryCache _memoryCache;
private readonly IServiceScopeFactory _serviceScopeFactory;
public PuppeteerWorker(
- IOptions config,
+ IOptions config,
IPuppeteerProcess puppeteerProcess,
ILogger logger,
+ IMemoryCache memoryCache,
IServiceScopeFactory serviceScopeFactory)
{
- _config = config.Value;
- _puppeteerProcess = puppeteerProcess;
- _logger = logger;
- _serviceScopeFactory = serviceScopeFactory;
+ _config = config.Value;
+ _puppeteerProcess = puppeteerProcess;
+ _logger = logger;
+ _memoryCache = memoryCache;
+ _serviceScopeFactory = serviceScopeFactory;
}
+ private IUserService _userService;
+
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
- DateTime? lastExecutedOn = null;
+ DateTime? lastExecutedOn = null;
+ bool operationOccurred = false;
- using (var scope = _serviceScopeFactory.CreateScope())
- {
- //IEnvelopeService envelopeService = scope.ServiceProvider.GetService();
+ using (var scope = _serviceScopeFactory.CreateScope())
+ {
+ _userService = scope.ServiceProvider.GetService();
- // This is how we keep the app running (in the background)
- while (!stoppingToken.IsCancellationRequested)
- {
- if (lastExecutedOn != null)
+ // This is how we keep the app running (in the background)
+ while (!stoppingToken.IsCancellationRequested)
{
- int minutesRemaining = _config.CheckIntervalInMinutes - (int)DateTime.UtcNow.Subtract(lastExecutedOn.Value).TotalMinutes;
- await Task.Delay(TimeSpan.FromMinutes(minutesRemaining < 0 ? 0 : minutesRemaining), stoppingToken);
+ // Keep Alive processing
+ operationOccurred = await ProcessUsersKeepalive();
+
+
+ _logger.LogInformation($"Operation occurred? {operationOccurred}");
+
+ // If no operation occurred, waits before looping again
+ if (lastExecutedOn != null && operationOccurred == false)
+ {
+ await Task.Delay(TimeSpan.FromMinutes(_config.TaskCheckIntervalMinutes), stoppingToken);
+ }
+
+ lastExecutedOn = DateTime.UtcNow;
+ _logger.LogInformation("PuppeteerWorker executed at: {time}", DateTimeOffset.Now);
}
+ }
+ }
- lastExecutedOn = DateTime.UtcNow;
- _logger.LogInformation("EnvelopeFundWorker running at: {time}", DateTimeOffset.Now);
+ private async Task ProcessUsersKeepalive()
+ {
+ bool operationOccurred = false;
- //await _puppeteerProcess.FundEnvelopes(envelopeService);
- }
- }
+ foreach (User user in _userService.GetAll().ToList())
+ {
+ int ka = _config.KeepAliveIntervalMinutes;
+ int uka = (int)DateTime.UtcNow.Subtract(GetUserLastExecution(PuppeteerConfigConstants.KeepAliveIntervalMinutes, user.Id)).TotalMinutes;
+
+ //_logger.LogInformation($"KeepAlive configured to {ka}. This user hasn't been kept alive in {uka} minute(s).");
+
+ if (_config.KeepAliveIntervalMinutes < (int)DateTime.UtcNow.Subtract(GetUserLastExecution(PuppeteerConfigConstants.KeepAliveIntervalMinutes, user.Id)).TotalMinutes)
+ {
+ await _puppeteerProcess.StayLoggedIn(user);
+ SetUserLastExecution(PuppeteerConfigConstants.KeepAliveIntervalMinutes, user.Id, DateTime.UtcNow);
+ operationOccurred = true;
+ _logger.LogInformation($"Operation set to true because of user {user.Id}");
+ }
+ }
+
+ return operationOccurred;
+ }
+
+ private DateTime GetUserLastExecution(string cacheKey, int userId)
+ {
+ var internalKeys = GetLastExecutionCachedDictionary(cacheKey);
+
+ if (!internalKeys.TryGetValue(userId, out var lastExecution))
+ {
+ _logger.LogInformation($"Could not find userId in '{cacheKey}' cache. Returning '{DateTime.MinValue}'.");
+ return DateTime.MinValue;
+ }
+
+ _logger.LogInformation($"Just got user {userId} from cache with value {lastExecution}");
+ return lastExecution;
+ }
+
+ private void SetUserLastExecution(string cacheKey, int userId, DateTime lastExecution)
+ {
+ var internalKeys = GetLastExecutionCachedDictionary(cacheKey);
+
+ if (internalKeys.ContainsKey(userId))
+ internalKeys[userId] = lastExecution;
+ else
+ internalKeys.Add(userId, lastExecution);
+
+ _memoryCache.Set(cacheKey, internalKeys);
+ _logger.LogInformation($"Just set user {userId} into cache with value {lastExecution}");
+ }
+
+ private Dictionary GetLastExecutionCachedDictionary(string cacheKey)
+ {
+ // Sets cache if no dictionary is found
+ if (!_memoryCache.TryGetValue>(cacheKey, out var internalKeys))
+ {
+ internalKeys = _userService.GetAll()
+ .ToDictionary(u => u.Id, u => DateTime.MinValue);
+ _memoryCache.Set(cacheKey, internalKeys);
+ _logger.LogInformation($"Updated users in '{cacheKey}' cache with new id list.");
+ }
+
+ return internalKeys;
+ }
+
+ private void PrintCacheValues(string cacheKey)
+ {
+ _logger.LogInformation($"Printing cache values from '{cacheKey}'");
+ Dictionary internalKeys = GetLastExecutionCachedDictionary(cacheKey);
+ foreach (KeyValuePair entry in internalKeys)
+ {
+ _logger.LogInformation($" {entry.Key} <=> {entry.Value}");
+ }
}
}
diff --git a/AAIntegration.SimmonsBank.API/appsettings.json b/AAIntegration.SimmonsBank.API/appsettings.json
index cb4ae10..1443388 100644
--- a/AAIntegration.SimmonsBank.API/appsettings.json
+++ b/AAIntegration.SimmonsBank.API/appsettings.json
@@ -25,7 +25,9 @@
"Secret": "5de80277015f9fd564c4d1cc2cf827dbb1774cd66e7d79aa258d9c35a9f67f32fc6cf0dc24244242bd9501288e0fd69e315b",
"APIUrl": "https://localhost:7260"
},
- "EnvelopeFund": {
- "CheckIntervalInMinutes": 10
+ "Puppeteer": {
+ "TaskCheckIntervalMinutes": 1,
+ "KeepAliveIntervalMinutes": 10,
+ "CheckForNewDataIntervalMinutes": 15
}
}