refactor: 优化项目配置、实体类和OSS服务
1. 调整RabbitMQ队列配置为新的业务队列 2. 修正Book实体类的列名映射为驼峰命名 3. 重构OSS服务的复制方法,支持自定义目标路径 4. 完善BookCreatedHandler,动态获取路由键并统一文件存储路径
This commit is contained in:
@ -13,6 +13,11 @@ namespace QuestionLibraryMQConsumer.Entities
|
||||
[SugarTable("book")]
|
||||
public partial class Book : SqlSugarBaseEntity
|
||||
{
|
||||
public Book()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// Desc:主键id
|
||||
/// Default:
|
||||
@ -34,7 +39,7 @@ namespace QuestionLibraryMQConsumer.Entities
|
||||
/// Default:
|
||||
/// Nullable:False
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "totalpage")]
|
||||
[SugarColumn(ColumnName = "totalPage")]
|
||||
public int TotalPage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@ -42,7 +47,7 @@ namespace QuestionLibraryMQConsumer.Entities
|
||||
/// Default:
|
||||
/// Nullable:False
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "verifypage")]
|
||||
[SugarColumn(ColumnName = "verifyPage")]
|
||||
public int VerifyPage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@ -58,7 +63,7 @@ namespace QuestionLibraryMQConsumer.Entities
|
||||
/// Default:
|
||||
/// Nullable:True
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "pdfurl")]
|
||||
[SugarColumn(ColumnName = "pdfUrl")]
|
||||
public string PdfUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@ -106,7 +111,7 @@ namespace QuestionLibraryMQConsumer.Entities
|
||||
/// Default:
|
||||
/// Nullable:True
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "backcover")]
|
||||
[SugarColumn(ColumnName = "backCover")]
|
||||
public string BackCover { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@ -114,7 +119,7 @@ namespace QuestionLibraryMQConsumer.Entities
|
||||
/// Default:
|
||||
/// Nullable:True
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "pdfpreviewurl")]
|
||||
[SugarColumn(ColumnName = "pdfPreviewUrl")]
|
||||
public string PdfPreviewUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@ -130,7 +135,7 @@ namespace QuestionLibraryMQConsumer.Entities
|
||||
/// Default:
|
||||
/// Nullable:True
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "downloadbookpagepdfname")]
|
||||
[SugarColumn(ColumnName = "downloadBookPagePdfName")]
|
||||
public string Downloadbookpagepdfname { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@ -138,7 +143,7 @@ namespace QuestionLibraryMQConsumer.Entities
|
||||
/// Default:b'0'
|
||||
/// Nullable:False
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "is_deleted")]
|
||||
[SugarColumn(ColumnName = "isDeleted")]
|
||||
public bool IsDeleted { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@ -146,7 +151,7 @@ namespace QuestionLibraryMQConsumer.Entities
|
||||
/// Default:
|
||||
/// Nullable:True
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "created_by")]
|
||||
[SugarColumn(ColumnName = "createdBy")]
|
||||
public long? CreatedBy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@ -154,7 +159,7 @@ namespace QuestionLibraryMQConsumer.Entities
|
||||
/// Default:
|
||||
/// Nullable:False
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "created_time")]
|
||||
[SugarColumn(ColumnName = "createdTime")]
|
||||
public DateTime CreatedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@ -162,7 +167,7 @@ namespace QuestionLibraryMQConsumer.Entities
|
||||
/// Default:
|
||||
/// Nullable:True
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "updated_by")]
|
||||
[SugarColumn(ColumnName = "updatedBy")]
|
||||
public long? UpdatedBy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@ -170,7 +175,7 @@ namespace QuestionLibraryMQConsumer.Entities
|
||||
/// Default:
|
||||
/// Nullable:True
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "updated_time")]
|
||||
[SugarColumn(ColumnName = "updatedTime")]
|
||||
public DateTime? UpdatedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@ -194,7 +199,8 @@ namespace QuestionLibraryMQConsumer.Entities
|
||||
/// Default:
|
||||
/// Nullable:True
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "source_id")]
|
||||
[SugarColumn(ColumnName = "sourceId")]
|
||||
public long SourceId { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ namespace QuestionLibraryMQConsumer.Entities
|
||||
///其他系统
|
||||
///</summary>
|
||||
[SugarTable("other_system")]
|
||||
public partial class OtherSystem : SqlSugarBaseEntity
|
||||
public partial class OtherSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// Desc:主键id
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
using QuestionLibraryMQConsumer.Data;
|
||||
using Microsoft.Extensions.Options;
|
||||
using QuestionLibraryMQConsumer.Configuration;
|
||||
using QuestionLibraryMQConsumer.Data;
|
||||
using QuestionLibraryMQConsumer.Entities;
|
||||
using QuestionLibraryMQConsumer.Models;
|
||||
using QuestionLibraryMQConsumer.Services;
|
||||
@ -6,6 +8,7 @@ using RabbitMQ.Client;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
@ -22,19 +25,26 @@ namespace QuestionLibraryMQConsumer.Handlers
|
||||
private readonly ILogger<BookCreatedHandler> _logger;
|
||||
private readonly QuestionLibraryDb _db;
|
||||
private readonly IOssService _ossService;
|
||||
private readonly string _routingKey;
|
||||
|
||||
public string RoutingKey => "questionLibrary.book.created";
|
||||
public string RoutingKey => _routingKey;
|
||||
public Type MessageType => typeof(BookCreatedMessage);
|
||||
public bool RequiresManualAck => false;
|
||||
|
||||
public BookCreatedHandler(
|
||||
ILogger<BookCreatedHandler> logger,
|
||||
QuestionLibraryDb db,
|
||||
IOssService ossService)
|
||||
IOssService ossService,
|
||||
IOptions<RabbitMqOptions> rabbitMqOptions)
|
||||
{
|
||||
_logger = logger;
|
||||
_db = db;
|
||||
_ossService = ossService;
|
||||
|
||||
var handlerTypeName = nameof(BookCreatedHandler);
|
||||
_routingKey = rabbitMqOptions.Value.Queues
|
||||
.FirstOrDefault(q => q.HandlerType == handlerTypeName)
|
||||
?.RoutingKey ?? string.Empty;
|
||||
}
|
||||
|
||||
public async Task HandleJsonAsync(string messageJson, CancellationToken cancellationToken)
|
||||
@ -86,17 +96,20 @@ namespace QuestionLibraryMQConsumer.Handlers
|
||||
|
||||
if (!string.IsNullOrEmpty(pdfUrl))
|
||||
{
|
||||
copyTasks.Add(CopyUrlAsync("PdfUrl", pdfUrl, otherSystem, newUrl => pdfUrl = newUrl, cancellationToken));
|
||||
var pdfExt = Path.GetExtension(pdfUrl);
|
||||
copyTasks.Add(CopyUrlAsync("PdfUrl", pdfUrl, $"book/{message.BookId}/book{pdfExt}", otherSystem, newUrl => pdfUrl = newUrl, cancellationToken));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(coverUrl))
|
||||
{
|
||||
copyTasks.Add(CopyUrlAsync("CoverUrl", coverUrl, otherSystem, newUrl => coverUrl = newUrl, cancellationToken));
|
||||
var coverExt = Path.GetExtension(coverUrl);
|
||||
copyTasks.Add(CopyUrlAsync("CoverUrl", coverUrl, $"book/{message.BookId}/cover{coverExt}", otherSystem, newUrl => coverUrl = newUrl, cancellationToken));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(backCoverUrl))
|
||||
{
|
||||
copyTasks.Add(CopyUrlAsync("BackCoverUrl", backCoverUrl, otherSystem, newUrl => backCoverUrl = newUrl, cancellationToken));
|
||||
var backCoverExt = Path.GetExtension(backCoverUrl);
|
||||
copyTasks.Add(CopyUrlAsync("BackCoverUrl", backCoverUrl, $"book/{message.BookId}/backCover{backCoverExt}", otherSystem, newUrl => backCoverUrl = newUrl, cancellationToken));
|
||||
}
|
||||
|
||||
if (copyTasks.Count > 0)
|
||||
@ -130,11 +143,11 @@ namespace QuestionLibraryMQConsumer.Handlers
|
||||
_logger.LogInformation("书籍 {BookId} 创建成功", message.BookId);
|
||||
}
|
||||
|
||||
private async Task CopyUrlAsync(string fieldName, string originalPath, OtherSystem otherSystem, Action<string> setNewPath, CancellationToken cancellationToken)
|
||||
private async Task CopyUrlAsync(string fieldName, string originalPath, string targetPath, OtherSystem otherSystem, Action<string> setNewPath, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
var newPath = await _ossService.CopyToOwnBucketAsync(originalPath, otherSystem.BucketName, cancellationToken);
|
||||
var newPath = await _ossService.CopyToOwnBucketAsync(originalPath, otherSystem.BucketName, targetPath, cancellationToken);
|
||||
setNewPath(newPath);
|
||||
_logger.LogInformation("{FieldName} OSS复制成功: {OriginalPath} -> {NewPath}", fieldName, originalPath, newPath);
|
||||
}
|
||||
|
||||
@ -9,5 +9,5 @@ public interface IOssService
|
||||
/// <param name="sourceBucket">源bucket名称</param>
|
||||
/// <param name="cancellationToken">取消令牌</param>
|
||||
/// <returns>复制后的新URL</returns>
|
||||
Task<string> CopyToOwnBucketAsync(string sourcePath, string sourceBucket, CancellationToken cancellationToken = default);
|
||||
Task<string> CopyToOwnBucketAsync(string sourcePath, string sourceBucket, string targetPath, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@ public class OssService : IOssService
|
||||
_ossOptions = ossOptions.Value;
|
||||
}
|
||||
|
||||
public async Task<string> CopyToOwnBucketAsync(string sourcePath, string sourceBucket, CancellationToken cancellationToken = default)
|
||||
public async Task<string> CopyToOwnBucketAsync(string sourcePath, string sourceBucket, string targetPath, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (string.IsNullOrEmpty(sourcePath))
|
||||
{
|
||||
@ -34,13 +34,13 @@ public class OssService : IOssService
|
||||
var client = new OssClient(_ossOptions.Endpoint, _ossOptions.AccessKeyID, _ossOptions.AccessKeySecret);
|
||||
|
||||
// 执行跨bucket复制
|
||||
var request = new CopyObjectRequest(sourceBucket, objectKey, _ossOptions.BucketName, objectKey);
|
||||
var request = new CopyObjectRequest(sourceBucket, objectKey, _ossOptions.BucketName, targetPath);
|
||||
var result = client.CopyObject(request);
|
||||
|
||||
_logger.LogInformation("OSS跨bucket复制成功: {SourceBucket}/{ObjectKey} -> {TargetBucket}/{TargetKey}, ETag: {ETag}",
|
||||
sourceBucket, objectKey, _ossOptions.BucketName, objectKey, result.ETag);
|
||||
sourceBucket, objectKey, _ossOptions.BucketName, targetPath, result.ETag);
|
||||
|
||||
return objectKey;
|
||||
return targetPath;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@ -10,25 +10,10 @@
|
||||
"PrefetchCount": 10,
|
||||
"Queues": [
|
||||
{
|
||||
"QueueName": "questionLibrary.book.created.queue",
|
||||
"ExchangeName": "icr.direct",
|
||||
"RoutingKey": "questionLibrary.book.created",
|
||||
"Durable": true,
|
||||
"Exclusive": false,
|
||||
"AutoDelete": false
|
||||
},
|
||||
{
|
||||
"QueueName": "questionLibrary.book.created.queue",
|
||||
"ExchangeName": "question.library.exchange.dev",
|
||||
"RoutingKey": "questionLibrary.book.created",
|
||||
"Durable": true,
|
||||
"Exclusive": false,
|
||||
"AutoDelete": false
|
||||
},
|
||||
{
|
||||
"QueueName": "questionLibrary.book.created.queue",
|
||||
"ExchangeName": "question.library.exchange",
|
||||
"RoutingKey": "questionLibrary.book.created",
|
||||
"QueueName": "mq.book.push",
|
||||
"ExchangeName": "ex.book.direct",
|
||||
"RoutingKey": "rk.book.push",
|
||||
"HandlerType": "BookCreatedHandler",
|
||||
"Durable": true,
|
||||
"Exclusive": false,
|
||||
"AutoDelete": false
|
||||
|
||||
Reference in New Issue
Block a user