fix: delivery engine nil pointer crash on startup (closes #17)
Store the *database.Database wrapper instead of calling .DB() eagerly at construction time. The GORM *gorm.DB is only available after the database's OnStart hook runs, but the engine constructor runs during fx resolution (before OnStart). Accessing .DB() lazily via the wrapper avoids the nil pointer panic.
This commit is contained in:
@@ -12,7 +12,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
"gorm.io/gorm"
|
|
||||||
"sneak.berlin/go/webhooker/internal/database"
|
"sneak.berlin/go/webhooker/internal/database"
|
||||||
"sneak.berlin/go/webhooker/internal/logger"
|
"sneak.berlin/go/webhooker/internal/logger"
|
||||||
)
|
)
|
||||||
@@ -46,7 +45,7 @@ type EngineParams struct {
|
|||||||
|
|
||||||
// Engine processes queued deliveries in the background.
|
// Engine processes queued deliveries in the background.
|
||||||
type Engine struct {
|
type Engine struct {
|
||||||
db *gorm.DB
|
database *database.Database
|
||||||
log *slog.Logger
|
log *slog.Logger
|
||||||
client *http.Client
|
client *http.Client
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
@@ -56,7 +55,7 @@ type Engine struct {
|
|||||||
// New creates and registers the delivery engine with the fx lifecycle.
|
// New creates and registers the delivery engine with the fx lifecycle.
|
||||||
func New(lc fx.Lifecycle, params EngineParams) *Engine {
|
func New(lc fx.Lifecycle, params EngineParams) *Engine {
|
||||||
e := &Engine{
|
e := &Engine{
|
||||||
db: params.DB.DB(),
|
database: params.DB,
|
||||||
log: params.Logger.Get(),
|
log: params.Logger.Get(),
|
||||||
client: &http.Client{
|
client: &http.Client{
|
||||||
Timeout: httpClientTimeout,
|
Timeout: httpClientTimeout,
|
||||||
@@ -110,7 +109,7 @@ func (e *Engine) run(ctx context.Context) {
|
|||||||
|
|
||||||
func (e *Engine) processPending(ctx context.Context) {
|
func (e *Engine) processPending(ctx context.Context) {
|
||||||
var deliveries []database.Delivery
|
var deliveries []database.Delivery
|
||||||
result := e.db.
|
result := e.database.DB().
|
||||||
Where("status IN ?", []database.DeliveryStatus{
|
Where("status IN ?", []database.DeliveryStatus{
|
||||||
database.DeliveryStatusPending,
|
database.DeliveryStatusPending,
|
||||||
database.DeliveryStatusRetrying,
|
database.DeliveryStatusRetrying,
|
||||||
@@ -196,13 +195,13 @@ func (e *Engine) deliverRetry(_ context.Context, d *database.Delivery) {
|
|||||||
|
|
||||||
// Determine attempt number from existing results
|
// Determine attempt number from existing results
|
||||||
var resultCount int64
|
var resultCount int64
|
||||||
e.db.Model(&database.DeliveryResult{}).Where("delivery_id = ?", d.ID).Count(&resultCount)
|
e.database.DB().Model(&database.DeliveryResult{}).Where("delivery_id = ?", d.ID).Count(&resultCount)
|
||||||
attemptNum := int(resultCount) + 1
|
attemptNum := int(resultCount) + 1
|
||||||
|
|
||||||
// Check if we should wait before retrying (exponential backoff)
|
// Check if we should wait before retrying (exponential backoff)
|
||||||
if attemptNum > 1 {
|
if attemptNum > 1 {
|
||||||
var lastResult database.DeliveryResult
|
var lastResult database.DeliveryResult
|
||||||
lookupErr := e.db.Where("delivery_id = ?", d.ID).Order("created_at DESC").First(&lastResult).Error
|
lookupErr := e.database.DB().Where("delivery_id = ?", d.ID).Order("created_at DESC").First(&lastResult).Error
|
||||||
if lookupErr == nil {
|
if lookupErr == nil {
|
||||||
shift := attemptNum - 2
|
shift := attemptNum - 2
|
||||||
if shift > 30 {
|
if shift > 30 {
|
||||||
@@ -330,7 +329,7 @@ func (e *Engine) recordResult(d *database.Delivery, attemptNum int, success bool
|
|||||||
Duration: durationMs,
|
Duration: durationMs,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := e.db.Create(result).Error; err != nil {
|
if err := e.database.DB().Create(result).Error; err != nil {
|
||||||
e.log.Error("failed to record delivery result",
|
e.log.Error("failed to record delivery result",
|
||||||
"delivery_id", d.ID,
|
"delivery_id", d.ID,
|
||||||
"error", err,
|
"error", err,
|
||||||
@@ -339,7 +338,7 @@ func (e *Engine) recordResult(d *database.Delivery, attemptNum int, success bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *Engine) updateDeliveryStatus(d *database.Delivery, status database.DeliveryStatus) {
|
func (e *Engine) updateDeliveryStatus(d *database.Delivery, status database.DeliveryStatus) {
|
||||||
if err := e.db.Model(d).Update("status", status).Error; err != nil {
|
if err := e.database.DB().Model(d).Update("status", status).Error; err != nil {
|
||||||
e.log.Error("failed to update delivery status",
|
e.log.Error("failed to update delivery status",
|
||||||
"delivery_id", d.ID,
|
"delivery_id", d.ID,
|
||||||
"status", status,
|
"status", status,
|
||||||
|
|||||||
Reference in New Issue
Block a user