BitzOrcas.Infrastructure 提供每个宿主和模块所依赖的横切基础设施服务——审计日志、时钟、文件存储、种子数据和可观测性原语。这些抽象在设计上是 ORM 无关的。
审计管道
BitzOrcas 使用基于 Channel 的异步审计管道,将审计收集与审计存储解耦:
请求 → RequestAuditMiddleware → IAuditLogger │ ▼ ChannelAuditQueue (Channel<T>) │ ▼ 后台 AuditWriter │ ┌─────────┴─────────┐ ▼ ▼ IAuditLogStore IRequestAuditSink (数据库存储) (邮件/webhook 等)核心接口
| 接口 | 用途 |
|---|---|
IAuditLogger | 入队审计条目(即发即弃) |
IAuditLogStore | 将审计记录持久化到数据库 |
IRequestAuditSink | 额外审计消费者的扩展点 |
IAuditTableInitializer | 在 schema 初始化时创建审计表 |
IAuditQueryPort | 查询审计日志(只读) |
IAuditRetentionPort | 执行保留/清理策略 |
默认行为
- API Shell 模式(无数据库):Null sink — 审计条目静默丢弃
- SqlSugar 路径:
SqlSugarAuditLogStore持久化到 7 个分片审计表 - 后台写入器:从
Channel<T>处理条目,不阻塞请求处理
时钟抽象
public interface IAppClock{ DateTimeOffset UtcNow { get; }}SystemClock— 生产实现,默认上海 UTC+8FixedClock— 用于测试确定性时间相关逻辑- 通过
Clock:Kind(Local或Utc)配置
种子框架
BitzOrcas 使用基于 CSV 的种子框架,而非 EF Core 迁移或 C# 种子方法:
架构
| 组件 | 用途 |
|---|---|
ISeedStep | 单个种子步骤的工作单元接口 |
ISeedRunner | 按依赖顺序编排所有注册的步骤 |
CsvSeedReader | 读取带头部映射的 CSV 文件 |
CsvSeedStepBase<T> | SqlSugar CSV 种子步骤的泛型基类 |
SeedRunReport | 执行结果(创建/更新/跳过计数) |
种子数据组织
Seeders/Assets/├── Identity/│ ├── platform_tenant.csv│ ├── sys_role.csv│ ├── sys_role_type.csv│ ├── sys_module.csv│ ├── sys_permission.csv│ └── sys_role_module_permission.csv└── MasterData/ ├── sys_country.csv ├── sys_language.csv ├── sys_general_code_group.csv ├── sys_general_code.csv ├── sys_general_code_text.csv ├── sys_exchange_rate.csv ├── sys_industry_setting.csv └── sys_public_holiday.csv种子数据工作原理
CsvSeedStepBase<T>读取 CSV,通过CsvSeedReader将列映射到实体属性- 使用 SqlSugar 的
StorageableAPI 实现upsert 语义——无重复错误 SeedRunner执行所有步骤,生成SeedRunReport- 通过
--init-schema --seed-demo或--seed-only标志触发
文件存储
BitzOrcas.Infrastructure.Storage 提供本地文件存储实现:
public interface IFileStorage{ Task<string> SaveAsync(Stream stream, string contentType, string extension, CancellationToken ct = default); Task<Stream?> ReadAsync(string path, CancellationToken ct = default); Task DeleteAsync(string path, CancellationToken ct = default);}LocalFileStorage— 将文件保存到可配置的磁盘目录- 通过
Storage:BasePath设置配置 - Files 模块(
FileAssetService)使用此抽象
当前用户访问
public interface ICurrentUser{ Guid? UserId { get; } string? TenantId { get; } string? UserName { get; } // ... 其他 claims}HttpContextCurrentUser(API 宿主)— 从 JWT claims 读取AnonymousCurrentUser(JobHost)— 无 HTTP 上下文可用ICurrentUserAccessor— 支持委托/任务上下文的运行身份份范围
程序集参考
BitzOrcas.Infrastructure ├── Auditing/ → IAuditLogger, ChannelAuditQueue, AuditEntryNormalizer ├── Clocking/ → SystemClock, FixedClock, IAppClock ├── Storage/ → LocalFileStorage, IFileStorage, LocalFileStorageOptions ├── Seeders/ → ISeedStep, ISeedRunner, CsvSeedReader, SeedRunner ├── Schema/ → IPersistenceSchemaInitializer ├── Users/ → CurrentUserAccessor, AnonymousCurrentUser ├── Http/ → ExternalRequestLoggingHandler └── Observability/ → ObservabilityExtensions (SqlSugar ActivitySource)