diff --git a/src/App/Extensions/CosmosDbServiceActivityExtensions.cs b/src/App/Extensions/CosmosDbServiceActivityExtensions.cs
index 73d6142b..73f09b87 100644
--- a/src/App/Extensions/CosmosDbServiceActivityExtensions.cs
+++ b/src/App/Extensions/CosmosDbServiceActivityExtensions.cs
@@ -86,7 +86,7 @@ public static class CosmosDbServiceActivityExtensions
/// The .
/// The ID of the user.
/// The started .
- public static Activity? StartDbGetLyricsAnalyzerUserRateLimitActivity(this ActivitySource activitySource, ulong userId) => StartDbGetLyricsAnalyzerUserRateLimitActivity(activitySource, userId, null);
+ public static Activity? StartDbGetLyricsAnalyzerUserRateLimitActivity(this ActivitySource activitySource, string userId) => StartDbGetLyricsAnalyzerUserRateLimitActivity(activitySource, userId, null);
///
/// Starts an activity for getting a lyrics analyzer rate limit for a user from the database.
@@ -95,14 +95,14 @@ public static class CosmosDbServiceActivityExtensions
/// The ID of the user.
/// The parent activity ID.
/// The started .
- public static Activity? StartDbGetLyricsAnalyzerUserRateLimitActivity(this ActivitySource activitySource, ulong userId, string? parentActivityId)
+ public static Activity? StartDbGetLyricsAnalyzerUserRateLimitActivity(this ActivitySource activitySource, string userId, string? parentActivityId)
{
return activitySource.StartActivity(
name: "Database:GetLyricsAnalyzerUserRateLimitAsync",
kind: ActivityKind.Internal,
tags: new ActivityTagsCollection
{
- { "userId", userId.ToString() }
+ { "userId", userId }
},
parentId: parentActivityId
);
diff --git a/src/App/Logging/CosmosDb/CosmosDbServiceLogging.cs b/src/App/Logging/CosmosDb/CosmosDbServiceLogging.cs
index eab9c283..332bd784 100644
--- a/src/App/Logging/CosmosDb/CosmosDbServiceLogging.cs
+++ b/src/App/Logging/CosmosDb/CosmosDbServiceLogging.cs
@@ -7,6 +7,31 @@ namespace MuzakBot.App.Logging.CosmosDb;
///
internal static partial class CosmosDbServiceLogging
{
+ ///
+ /// Logs the initialization of the database and ensures that it exists.
+ ///
+ /// The instance.
+ /// The name of the database.
+ [LoggerMessage(
+ EventName = "CosmosDbService.Initialize.EnsureDbExists",
+ Level = LogLevel.Information,
+ Message = "Ensuring that the database, '{databaseName}', exists."
+ )]
+ public static partial void LogInitializeEnsureDbExists(this ILogger logger, string databaseName);
+
+ ///
+ /// Logs the initialization of a container and ensures that it exists.
+ ///
+ /// The instance.
+ /// The name of the container.
+ /// The name of the database.
+ [LoggerMessage(
+ EventName = "CosmosDbService.Initialize.EnsureContainerExists",
+ Level = LogLevel.Information,
+ Message = "Ensuring that the container, '{containerName}', exists in '{databaseName}'."
+ )]
+ public static partial void LogInitializeEnsureContainerExists(this ILogger logger, string containerName, string databaseName);
+
///
/// Logs the start of an add or update operation to the database.
///
diff --git a/src/App/Models/Database/LyricsAnalyzer/LyricsAnalyzerUserRateLimit.cs b/src/App/Models/Database/LyricsAnalyzer/LyricsAnalyzerUserRateLimit.cs
index cf824632..aab24f51 100644
--- a/src/App/Models/Database/LyricsAnalyzer/LyricsAnalyzerUserRateLimit.cs
+++ b/src/App/Models/Database/LyricsAnalyzer/LyricsAnalyzerUserRateLimit.cs
@@ -16,7 +16,7 @@ public LyricsAnalyzerUserRateLimit()
/// Initializes a new instance of the class.
///
/// The user's ID.
- public LyricsAnalyzerUserRateLimit(ulong userId): this(userId, 0, DateTimeOffset.UtcNow)
+ public LyricsAnalyzerUserRateLimit(string userId): this(userId, 0, DateTimeOffset.UtcNow)
{}
///
@@ -24,7 +24,7 @@ public LyricsAnalyzerUserRateLimit(ulong userId): this(userId, 0, DateTimeOffset
///
/// The user's ID.
/// The current request count.
- public LyricsAnalyzerUserRateLimit(ulong userId, int currentRequestCount): this(userId, currentRequestCount, DateTimeOffset.UtcNow)
+ public LyricsAnalyzerUserRateLimit(string userId, int currentRequestCount): this(userId, currentRequestCount, DateTimeOffset.UtcNow)
{}
///
@@ -33,7 +33,7 @@ public LyricsAnalyzerUserRateLimit(ulong userId, int currentRequestCount): this(
/// The user's ID.
/// The current request count.
/// The last request time.
- public LyricsAnalyzerUserRateLimit(ulong userId, int currentRequestCount, DateTimeOffset lastRequestTime)
+ public LyricsAnalyzerUserRateLimit(string userId, int currentRequestCount, DateTimeOffset lastRequestTime)
{
Id = Guid.NewGuid().ToString();
PartitionKey = "user-item";
@@ -47,7 +47,7 @@ public LyricsAnalyzerUserRateLimit(ulong userId, int currentRequestCount, DateTi
/// The user's ID.
///
[JsonPropertyName("userId")]
- public ulong UserId { get; set; }
+ public string UserId { get; set; } = null!;
///
/// The current request count.
diff --git a/src/App/Models/Database/LyricsAnalyzer/interface/ILyricsAnalyzerUserRateLimit.cs b/src/App/Models/Database/LyricsAnalyzer/interface/ILyricsAnalyzerUserRateLimit.cs
index 3a5d0b53..a4f97d85 100644
--- a/src/App/Models/Database/LyricsAnalyzer/interface/ILyricsAnalyzerUserRateLimit.cs
+++ b/src/App/Models/Database/LyricsAnalyzer/interface/ILyricsAnalyzerUserRateLimit.cs
@@ -4,7 +4,7 @@ public interface ILyricsAnalyzerUserRateLimit
{
string Id { get; set; }
string PartitionKey { get; set; }
- ulong UserId { get; set; }
+ string UserId { get; set; }
int CurrentRequestCount { get; set; }
DateTimeOffset LastRequestTime { get; set; }
diff --git a/src/App/Modules/LyricsAnalyzerCommandModule/Commands/HandleLyricsAnalyzerAsync.cs b/src/App/Modules/LyricsAnalyzerCommandModule/Commands/HandleLyricsAnalyzerAsync.cs
index 510de530..396e236e 100644
--- a/src/App/Modules/LyricsAnalyzerCommandModule/Commands/HandleLyricsAnalyzerAsync.cs
+++ b/src/App/Modules/LyricsAnalyzerCommandModule/Commands/HandleLyricsAnalyzerAsync.cs
@@ -99,7 +99,7 @@ await FollowupAsync(
if (lyricsAnalyzerConfig.RateLimitEnabled)
{
_logger.LogInformation("Getting current rate limit for user '{UserId}' from database.", Context.User.Id);
- lyricsAnalyzerUserRateLimit = await _cosmosDbService.GetLyricsAnalyzerUserRateLimitAsync(Context.User.Id, activity?.Id);
+ lyricsAnalyzerUserRateLimit = await _cosmosDbService.GetLyricsAnalyzerUserRateLimitAsync(Context.User.Id.ToString(), activity?.Id);
_logger.LogInformation("Current rate limit for user '{UserId}' is {CurrentRequestCount}/{MaxRequests}.", Context.User.Id, lyricsAnalyzerUserRateLimit.CurrentRequestCount, lyricsAnalyzerConfig.RateLimitMaxRequests);
diff --git a/src/App/Program.cs b/src/App/Program.cs
index ffdd61a2..cad8e8f6 100644
--- a/src/App/Program.cs
+++ b/src/App/Program.cs
@@ -82,4 +82,8 @@
using var host = builder.Build();
+// Initialize the database and containers for the Cosmos DB service
+// before running the host.
+await host.Services.GetRequiredService().InitializeDatabaseAsync();
+
await host.RunAsync();
diff --git a/src/App/Services/CosmosDbService/CosmosDbService.cs b/src/App/Services/CosmosDbService/CosmosDbService.cs
index 04aebf96..a648e077 100644
--- a/src/App/Services/CosmosDbService/CosmosDbService.cs
+++ b/src/App/Services/CosmosDbService/CosmosDbService.cs
@@ -2,6 +2,7 @@
using Microsoft.Azure.Cosmos;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
+using MuzakBot.App.Logging.CosmosDb;
namespace MuzakBot.App.Services;
@@ -28,6 +29,44 @@ public CosmosDbService(ILogger logger, IOptions
+ /// Initializes the database and containers for MuzakBot.
+ ///
+ ///
+ public async Task InitializeDatabaseAsync()
+ {
+ // Initialize the database and containers for 'lyrics-analyzer',
+ // if they don't exist.
+ _logger.LogInitializeEnsureDbExists("lyrics-analyzer");
+ Database lyricsAnalyzerDb = await _cosmosDbClient.CreateDatabaseIfNotExistsAsync(
+ id: "lyrics-analyzer"
+ );
+
+ _logger.LogInitializeEnsureContainerExists("song-lyrics", "lyrics-analyzer");
+ await lyricsAnalyzerDb.CreateContainerIfNotExistsAsync(
+ id: "song-lyrics",
+ partitionKeyPath: "/partitionKey"
+ );
+
+ _logger.LogInitializeEnsureContainerExists("command-configs", "lyrics-analyzer");
+ await lyricsAnalyzerDb.CreateContainerIfNotExistsAsync(
+ id: "command-configs",
+ partitionKeyPath: "/partitionKey"
+ );
+
+ _logger.LogInitializeEnsureContainerExists("prompt-styles", "lyrics-analyzer");
+ await lyricsAnalyzerDb.CreateContainerIfNotExistsAsync(
+ id: "prompt-styles",
+ partitionKeyPath: "/partitionKey"
+ );
+
+ _logger.LogInitializeEnsureContainerExists("rate-limit", "lyrics-analyzer");
+ await lyricsAnalyzerDb.CreateContainerIfNotExistsAsync(
+ id: "rate-limit",
+ partitionKeyPath: "/partitionKey"
+ );
+ }
+
///
public void Dispose()
{
diff --git a/src/App/Services/CosmosDbService/LyricsAnalyzer/GetLyricsAnalyzerUserRateLimitAsync.cs b/src/App/Services/CosmosDbService/LyricsAnalyzer/GetLyricsAnalyzerUserRateLimitAsync.cs
index 384fb040..dc91f87c 100644
--- a/src/App/Services/CosmosDbService/LyricsAnalyzer/GetLyricsAnalyzerUserRateLimitAsync.cs
+++ b/src/App/Services/CosmosDbService/LyricsAnalyzer/GetLyricsAnalyzerUserRateLimitAsync.cs
@@ -16,7 +16,7 @@ public partial class CosmosDbService
///
/// The ID of the user.
/// The retrieved lyrics analyzer rate limit for the user.
- public async Task GetLyricsAnalyzerUserRateLimitAsync(ulong userId) => await GetLyricsAnalyzerUserRateLimitAsync(userId, null);
+ public async Task GetLyricsAnalyzerUserRateLimitAsync(string userId) => await GetLyricsAnalyzerUserRateLimitAsync(userId, null);
///
/// Gets the lyrics analyzer rate limit for a user from the database.
@@ -24,7 +24,7 @@ public partial class CosmosDbService
/// The ID of the user.
/// The parent activity ID.
/// The retrieved lyrics analyzer rate limit for the user.
- public async Task GetLyricsAnalyzerUserRateLimitAsync(ulong userId, string? parentActivityId)
+ public async Task GetLyricsAnalyzerUserRateLimitAsync(string userId, string? parentActivityId)
{
using var activity = _activitySource.StartDbGetLyricsAnalyzerUserRateLimitActivity(
userId: userId,
diff --git a/src/App/Services/CosmosDbService/interfaces/ICosmosDbService.cs b/src/App/Services/CosmosDbService/interfaces/ICosmosDbService.cs
index e435b5df..925662c7 100644
--- a/src/App/Services/CosmosDbService/interfaces/ICosmosDbService.cs
+++ b/src/App/Services/CosmosDbService/interfaces/ICosmosDbService.cs
@@ -4,14 +4,16 @@ namespace MuzakBot.App.Services;
public interface ICosmosDbService : IDisposable
{
+ Task InitializeDatabaseAsync();
+
Task GetLyricsAnalyzerConfigAsync();
Task GetLyricsAnalyzerConfigAsync(string? parentActivityId);
Task AddOrUpdateLyricsAnalyzerConfigAsync(LyricsAnalyzerConfig lyricsAnalyzerConfig);
Task AddOrUpdateLyricsAnalyzerConfigAsync(LyricsAnalyzerConfig lyricsAnalyzerConfig, string? parentActivityId);
- Task GetLyricsAnalyzerUserRateLimitAsync(ulong userId);
- Task GetLyricsAnalyzerUserRateLimitAsync(ulong userId, string? parentActivityId);
+ Task GetLyricsAnalyzerUserRateLimitAsync(string userId);
+ Task GetLyricsAnalyzerUserRateLimitAsync(string userId, string? parentActivityId);
Task AddOrUpdateLyricsAnalyzerUserRateLimitAsync(LyricsAnalyzerUserRateLimit lyricsAnalyzerUserRateLimit);
Task AddOrUpdateLyricsAnalyzerUserRateLimitAsync(LyricsAnalyzerUserRateLimit lyricsAnalyzerUserRateLimit, string? parentActivityId);