check / check (push) Waiting to run
The main database, each webhook's event database and each archive file get their schema from SQL files under internal/db/migrations/, one directory per kind. Opening a file runs, in one transaction, each file that schema_migrations does not list. GORM stays for queries. AutoMigrate is gone, tests included. An event database holds only its own tables now, so the sweep that removed target rows copied into it is deleted. The association guard stays: without it a delivery write fails on the missing targets table. The event totals row is inserted by events/001_schema.sql rather than on every open. Model: opus-5-5
55 lines
1.7 KiB
Go
55 lines
1.7 KiB
Go
package database
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/clause"
|
|
)
|
|
|
|
// omitAssociationsCallback is the name the association guard is
|
|
// registered under on a per-webhook database's create and update
|
|
// callback chains.
|
|
const omitAssociationsCallback = "webhooker:omit_associations"
|
|
|
|
// omitAssociations makes every create and update issued against a
|
|
// per-webhook database skip GORM's automatic association save.
|
|
//
|
|
// A per-webhook database holds the event tier only, but Delivery
|
|
// declares belongs-to Event and Target and the delivery engine fills
|
|
// both in memory before writing. Without this guard GORM upserts those
|
|
// parent rows here on the delivery and retry write paths, and the
|
|
// target, whose config holds destination URLs and bearer credentials,
|
|
// goes to a targets table this file does not have, which fails the
|
|
// write. Registering the guard on the connection
|
|
// covers every write path, including writes inside a transaction and
|
|
// write paths added later. Every event-tier row this file holds is
|
|
// written explicitly, so nothing depends on the automatic save.
|
|
func omitAssociations(db *gorm.DB) error {
|
|
omit := func(tx *gorm.DB) {
|
|
tx.Statement.Omits = append(
|
|
tx.Statement.Omits, clause.Associations,
|
|
)
|
|
}
|
|
|
|
err := db.Callback().Create().
|
|
Before("gorm:save_before_associations").
|
|
Register(omitAssociationsCallback, omit)
|
|
if err != nil {
|
|
return fmt.Errorf(
|
|
"registering create association guard: %w", err,
|
|
)
|
|
}
|
|
|
|
err = db.Callback().Update().
|
|
Before("gorm:save_before_associations").
|
|
Register(omitAssociationsCallback, omit)
|
|
if err != nil {
|
|
return fmt.Errorf(
|
|
"registering update association guard: %w", err,
|
|
)
|
|
}
|
|
|
|
return nil
|
|
}
|