Skip to main content

Repository Pattern

It provides an abstraction layer between the application's business logic and the data storage, which could be a database, an API, a file system, or any other data source. The primary goal of the Repository Pattern is to separate the concerns of data access and data manipulation from the core application logic.

Domain Declaration

Auditing

type AuditedModel struct {
CreatedBy *string
UpdatedBy *string
CreatedAt time.Time `gorm:"timestamp"`
UpdatedAt time.Time `gorm:"timestamp"`
}

AggregateRoot

type Agg interface {
AppendEvent(events ...event.Event)
ConsumeEventsIfAny(ctx context.Context, fn func(ctx context.Context, events []event.Event) error) (err error)
}

type AggRoot struct {
events []event.Event
}

AggRoot implements Agg interface to hold events to be committed when db transactions being committed

Repository Interface

type Repo[TEntity any, TKey any, TQuery any] interface {
List(ctx context.Context, query TQuery) ([]*TEntity, error)
ListCursor(ctx context.Context, query TQuery) (*CursorResult[TEntity], error)
First(ctx context.Context, query TQuery) (*TEntity, error)
Count(ctx context.Context, query TQuery) (total int64, filtered int64, err error)
Get(ctx context.Context, id TKey) (*TEntity, error)
Create(ctx context.Context, entity *TEntity) error
BatchCreate(ctx context.Context, entity []*TEntity, batchSize int) error
Update(ctx context.Context, id TKey, entity *TEntity, p query.Select) error
Upsert(ctx context.Context, entity *TEntity) error
Delete(ctx context.Context, id TKey) error
}

To achieve CRUD functionality more quickly, kit provides default implementations of the above interfaces. You can swiftly implement a repository using the "embed struct" approach.

Entity Change Events

The default implementation of repository will trigger the following local events

type BeforeCreate[TEntity any] struct {
Entity TEntity
}

type AfterCreate[TEntity any] struct {
Entity TEntity
}
type BeforeUpdate[TEntity any] struct {
Entity TEntity
P query.Select
}

type AfterUpdate[TEntity any] struct {
Entity TEntity
}
type BeforeDelete[TEntity any] struct {
Entity TEntity
}
type AfterDelete[TEntity any] struct {
Entity TEntity
}