| {{/* |
| This template exposes client internals (like the driver) so they can be shared accross instances. |
| The intended usecase is for shared transaction management accross multiple db.Client and db.Tx instances |
| using the same connection. |
| |
| This template has to be included in each entgo codegen that wants to parttake in shared transactions. |
| |
| // TODO: Tx.onRollback and Tx.onCommit hooks are ignored when using shared transactions, fix this |
| */}} |
| {{ define "expose" }} |
| |
| |
| {{/* Add the base header for the generated file */}} |
| {{ $pkg := base $.Config.Package }} |
| {{ template "header" $ }} |
| |
| {{/* Expose internals of a Client so it can be used by transaction management */}} |
| func (c *Client) GetConfig() *entutils.RawEntConfig { |
| return &entutils.RawEntConfig{ |
| Driver: c.config.driver, |
| Debug: c.config.debug, |
| Log: c.config.log, |
| } |
| } |
| {{/* Expose internals of a Transactional Client so it can be used by transaction management */}} |
| // ignores hooks and intersectors |
| type ExposedTxDriver struct { |
| Driver *txDriver |
| } |
| |
| var _ entutils.Transactable = (*ExposedTxDriver)(nil) |
| |
| func (d *ExposedTxDriver) Rollback() error { |
| return d.Driver.tx.Rollback() |
| } |
| |
| func (d *ExposedTxDriver) Commit() error { |
| return d.Driver.tx.Commit() |
| } |
| |
| func (d *ExposedTxDriver) SavePoint(name string) error { |
| _, err := d.Driver.ExecContext(context.Background(), "SAVEPOINT " + name) |
| return err |
| } |
| |
| func (d *ExposedTxDriver) RollbackTo(name string) error { |
| _, err := d.Driver.ExecContext(context.Background(), "ROLLBACK TO " + name) |
| return err |
| } |
| |
| func (d *ExposedTxDriver) Release(name string) error { |
| _, err := d.Driver.ExecContext(context.Background(), "RELEASE SAVEPOINT " + name) |
| return err |
| } |
| |
| // HijackTx returns a new transaction driver with the provided options. |
| // The returned transaction can later be used to instanciate new clients. |
| func (c *Client) HijackTx(ctx context.Context, opts *sql.TxOptions) (context.Context, *entutils.RawEntConfig, *ExposedTxDriver, error) { |
| if _, ok := c.driver.(*txDriver); ok { |
| return nil, nil, nil, errors.New("ent: cannot start a transaction within a transaction") |
| } |
| tx, err := c.driver.(interface { |
| BeginTx(context.Context, *sql.TxOptions) (dialect.Tx, error) |
| }).BeginTx(ctx, opts) |
| if err != nil { |
| return nil, nil, nil, fmt.Errorf("ent: starting a transaction: %w", err) |
| } |
| |
| driver := &txDriver{tx: tx, drv: c.driver} |
| |
| cfg := c.config |
| cfg.driver = &txDriver{tx: tx, drv: c.driver} |
| return ctx, &entutils.RawEntConfig{ |
| Driver: cfg.driver, |
| Debug: cfg.debug, |
| Log: cfg.log, |
| }, &ExposedTxDriver{Driver: driver}, nil |
| } |
| |
| // NewTxClientFromConfig creates a new transactional client from a (hijacked) configuration. |
| func NewTxClientFromRawConfig(ctx context.Context, cfg entutils.RawEntConfig) *Tx { |
| config := config{ |
| driver: cfg.Driver, |
| debug: cfg.Debug, |
| log: cfg.Log, |
| hooks: &hooks{}, |
| inters: &inters{}, |
| } |
| |
| return &Tx{ |
| ctx: ctx, |
| config: config, |
| // Clients templated from defined schemas |
| {{ range $n := $.Nodes }} |
| {{ $n.Name }}: New{{ $n.Name }}Client(config), |
| {{ end }} |
| } |
| } |
| |
| |
| {{ end }} |
| |