Architecture & Core Data
Clean architecture implementation details, common patterns (Result Pattern, Unit of Work), and global base classes used throughout Arthix.
Architecture Layers
┌─────────────────────────────────────────────────────┐
│ Arthix.API (Presentation) │
│ Controllers → HandleResult() → HTTP Response │
├─────────────────────────────────────────────────────┤
│ Arthix.Application (Business Logic) │
│ Service Interfaces │ DTOs │ Validators │
├─────────────────────────────────────────────────────┤
│ Arthix.Infrastructure (Implementations) │
│ EF Core │ Azure │ RabbitMQ │ SignalR │ Meta API │
├─────────────────────────────────────────────────────┤
│ Arthix.Domain (Core) │
│ BaseEntity │ IRepository │ IUnitOfWork │ Entities │
├─────────────────────────────────────────────────────┤
│ Arthix.Shared (Cross-Cutting) │
│ Result Pattern │ Enums │ DTOs │ Configuration │
├─────────────────────────────────────────────────────┤
│ Arthix.Worker (Background) │
│ RabbitMQ Consumer │ Scheduled Actions │ SignalR │
└─────────────────────────────────────────────────────┘
Dependency Flow: API → Application → Domain ← Infrastructure ← Worker, Shared used by all.
BaseEntity
C#
public abstract class BaseEntity : ISoftDeletable
{
[Key] public Guid Id { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime? UpdatedAt { get; set; }
public Guid? CreatedBy { get; set; }
public Guid? UpdatedBy { get; set; }
public bool IsDeleted { get; set; } = false;
}Note: EF Core global query filters auto-exclude IsDeleted = true rows.
Result Pattern
| ResultType | HTTP | When To Use |
|---|---|---|
Success | 200 | Operation succeeded |
Failure | 500 | Unexpected internal error |
ValidationError | 400 | Input validation failed |
NotFound | 404 | Entity not in database |
Unauthorized | 401 | Auth/permission failure |
BadRequest | 400 | Malformed request data |
NotModified | 304 | No changes applied |
C#
// Service usage:
return Result.Success(myDto, "Created successfully");
return Result.NotFound<MyDto>("Contact not found");
return Result.ValidationError<MyDto>(new List<string> { "Email is required" });
// Controller:
var result = await _service.DoSomethingAsync(request, ct);
return HandleResult(result);IRepository & IUnitOfWork Interfaces
C#
public interface IRepository<T> where T : BaseEntity
{
Task<T?> GetByIdAsync(Guid id, CancellationToken ct);
Task<IEnumerable<T>> GetAllAsync(CancellationToken ct);
Task<IEnumerable<T>> FindAsync(Expression<Func<T, bool>> predicate, CancellationToken ct);
Task<T> AddAsync(T entity, CancellationToken ct);
Task UpdateAsync(T entity, CancellationToken ct);
Task DeleteAsync(Guid id, CancellationToken ct); // Soft delete
Task<bool> ExistsAsync(Expression<Func<T, bool>> predicate, CancellationToken ct);
}
public interface IUnitOfWork : IDisposable
{
Task<int> SaveChangesAsync(CancellationToken ct);
Task BeginTransactionAsync(CancellationToken ct);
Task CommitTransactionAsync(CancellationToken ct);
Task RollbackTransactionAsync(CancellationToken ct);
}DbContext — DbSets
| DbSet | Entity Group | Module |
|---|---|---|
Firms, FirmAddresses, FirmSettings | Firm entities | Firm |
FirmUsers, FirmUserRelations, FirmUserRefreshTokens | Auth entities | Auth/User |
FirmContacts, FirmContactPhones, FirmContactEmails... | Contact entities | Contact |
MetaWhatsappConfigurations, MetaWebhooks, MetaObjectLogs | Meta configuration | |
WhatsappTemplates, WhatsappTemplateComponents... | Templates | |
WhatsappGroups, WhatsappMessages, WhatsappMessageObjs | Messaging | |
Workflows, WorkflowNodes, WorkflowEdges... | Workflow entities | Workflow |
Notifications | Notifications | Notifications |
JSONB Columns (PostgreSQL):
WorkflowNode.Configuration— Node-specific settingsWorkflowExecution.WorkflowJson— Snapshot at execution timeWorkflowNodeExecution.InputData,OutputData,ErrorData— Node I/ONotification.Metadata— Per-module extra data
Migration Commands
Bash
# Create migration
dotnet ef migrations add MigrationName --project src/Arthix.Infrastructure --startup-project src/Arthix.API
# Apply migration
dotnet ef database update --project src/Arthix.Infrastructure --startup-project src/Arthix.API