go-transaction-manager
124 строки · 2.9 Кб
1package manager2
3import (4"context"5
6"github.com/avito-tech/go-transaction-manager/trm/v2"7)
8
9// ChainedMW starts transactions in the order given and commit/rollback in reverse order.
10//
11// WARNING: Rollback of last transactions isn't affected done commits.
12// ChainedMW should be only used if the application can tolerate or
13// recover from an inconsistent state caused by partially committed transactions.
14type ChainedMW struct {15do nextDo
16doWithSettings nextDoWithSettings
17}
18
19// NewChained creates *ChainedMW or chained trm.Manager.
20func NewChained(mm []trm.Manager, _ ...Opt) (*ChainedMW, error) {21if len(mm) == 0 {22return &ChainedMW{23do: nilNextDo,24doWithSettings: nilNextDoWithSettings,25}, nil26}27
28last := len(mm) - 129do := newLastDo(mm[last])30doWithSettings := newLastDoWithSettings(mm[last])31
32for index := last - 1; index >= 0; index-- {33do = newNextDo(mm[index], do)34doWithSettings = newNextDoWithSettings(mm[index], doWithSettings)35}36
37return &ChainedMW{38do: do,39doWithSettings: doWithSettings,40}, nil41}
42
43// MustChained returns ChainedMW if err is nil and panics otherwise.
44func MustChained(mm []trm.Manager, oo ...Opt) *ChainedMW {45s, err := NewChained(mm, oo...)46if err != nil {47panic(err)48}49
50return s51}
52
53//revive:disable:exported
54func (c *ChainedMW) Do(55ctx context.Context,56fn func(ctx context.Context) error,57) error {58return c.do(ctx, fn)59}
60
61type callback func(ctx context.Context) error62
63type nextDo func(ctx context.Context, fn callback) error64
65func nilNextDo(ctx context.Context, fn callback) error {66return fn(ctx)67}
68
69func newNextDo(m trm.Manager, n nextDo) nextDo {70return func(ctx context.Context, fn callback) error {71return m.Do(ctx, func(ctx context.Context) error {72return n(ctx, fn)73})74}75}
76
77func newLastDo(m trm.Manager) nextDo {78return func(ctx context.Context, fn callback) error {79return m.Do(ctx, fn)80}81}
82
83// DoWithSettings is an implementation of trm.Manager.
84//
85// WARNING: trm.CtxKey should not be set in trm.Settings otherwise all trm.Manager would get same trm.Transaction from context.Context.
86func (c *ChainedMW) DoWithSettings(87ctx context.Context,88s trm.Settings,89fn func(ctx context.Context) error,90) error {91return c.doWithSettings(ctx, s, fn)92}
93
94type nextDoWithSettings func(context.Context, trm.Settings, callback) error95
96func nilNextDoWithSettings(97ctx context.Context,98_ trm.Settings,99fn callback,100) error {101return fn(ctx)102}
103
104func newNextDoWithSettings(m trm.Manager, n nextDoWithSettings) nextDoWithSettings {105return func(106ctx context.Context,107s trm.Settings,108fn callback,109) error {110return m.DoWithSettings(ctx, s, func(ctx context.Context) error {111return n(ctx, s, fn)112})113}114}
115
116func newLastDoWithSettings(m trm.Manager) nextDoWithSettings {117return func(118ctx context.Context,119s trm.Settings,120fn callback,121) error {122return m.DoWithSettings(ctx, s, fn)123}124}
125