check / check (push) Waiting to run
Replaces #559, which conflicted. 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
|
|
}
|