Skip to content
bitzorcas
EN

Reference

Shared infrastructure building block

Cross-cutting infrastructure services — audit pipeline (channel queue + async writer), clock abstraction, seed framework (CSV-based), local file storage, and observability foundations.

Last updated

BitzOrcas.Infrastructure provides the cross-cutting infrastructure services that every host and module depends on — audit logging, clock, file storage, seed data, and observability primitives. These are ORM-agnostic by design.

Audit pipeline

BitzOrcas uses a channel-based async audit pipeline that decouples audit collection from audit storage:

Request → RequestAuditMiddleware → IAuditLogger
ChannelAuditQueue (Channel<T>)
Background AuditWriter
┌─────────┴─────────┐
▼ ▼
IAuditLogStore IRequestAuditSink
(DB storage) (email/webhook, etc.)

Key interfaces

InterfacePurpose
IAuditLoggerEnqueue audit entries (fire-and-forget)
IAuditLogStorePersist audit records to database
IRequestAuditSinkExtension point for additional audit consumers
IAuditTableInitializerCreate audit tables during schema init
IAuditQueryPortQuery audit logs (read-only)
IAuditRetentionPortExecute retention/cleanup policies

Default behavior

  • API Shell mode (no DB): Null sinks — audit entries are silently dropped
  • SqlSugar path: SqlSugarAuditLogStore persists to 7 sharded audit tables
  • Background writer: Processes entries from Channel<T> without blocking request handling

Clock abstraction

public interface IAppClock
{
DateTimeOffset UtcNow { get; }
}
  • SystemClock — production implementation, defaults to Shanghai UTC+8
  • FixedClock — for testing deterministic time-dependent logic
  • Configurable via Clock:Kind (Local or Utc)

Seed framework

BitzOrcas uses a CSV-based seed framework instead of EF Core migrations or C# seed methods:

Architecture

ComponentPurpose
ISeedStepUnit-of-work interface for a single seed step
ISeedRunnerOrchestrates all registered steps in dependency order
CsvSeedReaderReads CSV files with header mapping
CsvSeedStepBase<T>Generic base for SqlSugar CSV seed steps
SeedRunReportExecution results (created/updated/skipped counts)

Seed data organization

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

How seeding works

  1. CsvSeedStepBase<T> reads the CSV, maps columns to entity properties via CsvSeedReader
  2. Uses SqlSugar’s Storageable API for upsert semantics — no duplicate errors
  3. SeedRunner executes all steps, produces a SeedRunReport
  4. Triggered via --init-schema --seed-demo or --seed-only flags

File storage

BitzOrcas.Infrastructure.Storage provides a local file storage implementation:

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 — saves files to a configurable directory on disk
  • Configurable via Storage:BasePath setting
  • Files module (FileAssetService) uses this abstraction

Current user access

public interface ICurrentUser
{
Guid? UserId { get; }
string? TenantId { get; }
string? UserName { get; }
// ... additional claims
}
  • HttpContextCurrentUser (API Host) — reads from JWT claims
  • AnonymousCurrentUser (JobHost) — no HTTP context available
  • ICurrentUserAccessor — enables run-as scoping for delegation/job contexts

Assembly reference

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)