fix: align backend APIs and upload flow

This commit is contained in:
2026-09-15 14:10:55 +08:00
parent 32177a7293
commit 53e6195938
149 changed files with 4791 additions and 435 deletions
@@ -0,0 +1,25 @@
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
namespace MessageService.Infrastructure.Migrations
{
[DbContext(typeof(MessageDbContext))]
[Migration("20260909000100_ApiAlignmentFixes")]
public partial class ApiAlignmentFixes : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateIndex(
name: "IX_conversations_UserId_ChatType_TargetId_IsDeleted",
table: "conversations",
columns: new[] { "UserId", "ChatType", "TargetId", "IsDeleted" });
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_conversations_UserId_ChatType_TargetId_IsDeleted",
table: "conversations");
}
}
}
@@ -0,0 +1,81 @@
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
namespace MessageService.Infrastructure.Migrations
{
[DbContext(typeof(MessageDbContext))]
[Migration("20260911000100_ConversationUniqueness")]
public partial class ConversationUniqueness : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("""
CREATE TEMPORARY TABLE `conversation_dedup` AS
SELECT
`Id`,
ROW_NUMBER() OVER (
PARTITION BY `UserId`, `ChatType`, `TargetId`
ORDER BY COALESCE(`ModificationTime`, `CreationTime`) DESC, `Id` DESC
) AS `row_num`,
MAX(`UnreadCount`) OVER (
PARTITION BY `UserId`, `ChatType`, `TargetId`
) AS `max_unread_count`,
MAX(`LastReadSequenceId`) OVER (
PARTITION BY `UserId`, `ChatType`, `TargetId`
) AS `max_last_read_sequence_id`
FROM `conversations`
WHERE `IsDeleted` = 0;
""");
migrationBuilder.Sql("""
UPDATE `conversations` AS `conversation`
INNER JOIN `conversation_dedup` AS `dedup` ON `conversation`.`Id` = `dedup`.`Id`
SET
`conversation`.`UnreadCount` = CASE
WHEN `dedup`.`row_num` = 1 THEN `dedup`.`max_unread_count`
ELSE `conversation`.`UnreadCount`
END,
`conversation`.`LastReadSequenceId` = CASE
WHEN `dedup`.`row_num` = 1 THEN `dedup`.`max_last_read_sequence_id`
ELSE `conversation`.`LastReadSequenceId`
END,
`conversation`.`IsDeleted` = CASE
WHEN `dedup`.`row_num` = 1 THEN `conversation`.`IsDeleted`
ELSE 1
END,
`conversation`.`Deletion` = CASE
WHEN `dedup`.`row_num` = 1 THEN `conversation`.`Deletion`
ELSE CURRENT_TIMESTAMP(6)
END;
""");
migrationBuilder.Sql("DROP TEMPORARY TABLE `conversation_dedup`;");
migrationBuilder.AddColumn<string>(
name: "ActiveConversationKey",
table: "conversations",
type: "varchar(96)",
maxLength: 96,
nullable: true,
computedColumnSql: "CASE WHEN `IsDeleted` = 0 THEN CONCAT(`UserId`, ':', `ChatType`, ':', `TargetId`) ELSE NULL END",
stored: true);
migrationBuilder.CreateIndex(
name: "UX_conversations_ActiveConversationKey",
table: "conversations",
column: "ActiveConversationKey",
unique: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "UX_conversations_ActiveConversationKey",
table: "conversations");
migrationBuilder.DropColumn(
name: "ActiveConversationKey",
table: "conversations");
}
}
}
@@ -0,0 +1,48 @@
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
namespace MessageService.Infrastructure.Migrations
{
[DbContext(typeof(MessageDbContext))]
[Migration("20260913000100_ConversationActivityAndMessageSearch")]
public partial class ConversationActivityAndMessageSearch : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTimeOffset>(
name: "LastMessageTime",
table: "conversations",
type: "datetime(6)",
nullable: true);
migrationBuilder.Sql("""
UPDATE `conversations` AS `conversation`
SET `conversation`.`LastMessageTime` = COALESCE(
(
SELECT MAX(`message`.`CreationTime`)
FROM `messages` AS `message`
WHERE `message`.`StreamKey` = `conversation`.`StreamKey`
AND `message`.`IsDeleted` = 0
),
`conversation`.`CreationTime`
);
""");
migrationBuilder.CreateIndex(
name: "IX_messages_StreamKey_MsgType_State_SequenceId",
table: "messages",
columns: new[] { "StreamKey", "MsgType", "State", "SequenceId" });
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_messages_StreamKey_MsgType_State_SequenceId",
table: "messages");
migrationBuilder.DropColumn(
name: "LastMessageTime",
table: "conversations");
}
}
}
@@ -25,6 +25,12 @@ namespace MessageService.Infrastructure.Migrations
modelBuilder.Entity("MessageService.Domain.Entities.Conversation", b =>
{
b.Property<string>("ActiveConversationKey")
.ValueGeneratedOnAddOrUpdate()
.HasMaxLength(96)
.HasColumnType("varchar(96)")
.HasComputedColumnSql("CASE WHEN `IsDeleted` = 0 THEN CONCAT(`UserId`, ':', `ChatType`, ':', `TargetId`) ELSE NULL END", true);
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
@@ -45,6 +51,9 @@ namespace MessageService.Infrastructure.Migrations
.IsRequired()
.HasColumnType("longtext");
b.Property<DateTimeOffset?>("LastMessageTime")
.HasColumnType("datetime(6)");
b.Property<long?>("LastReadSequenceId")
.HasColumnType("bigint");
@@ -74,8 +83,14 @@ namespace MessageService.Infrastructure.Migrations
b.HasKey("Id");
b.HasIndex("ActiveConversationKey")
.IsUnique()
.HasDatabaseName("UX_conversations_ActiveConversationKey");
b.HasIndex("UserId");
b.HasIndex("UserId", "ChatType", "TargetId", "IsDeleted");
b.ToTable("conversations", (string)null);
});
@@ -176,6 +191,8 @@ namespace MessageService.Infrastructure.Migrations
b.HasIndex("StreamKey", "SequenceId");
b.HasIndex("StreamKey", "MsgType", "State", "SequenceId");
b.ToTable("messages", (string)null);
});
#pragma warning restore 612, 618