3535
3636 completed bool
3737
38- onCompleted xsync.Set [* baseTx.OnTransactionCompletedFunc ]
38+ onBeforeCommit xsync.Set [* baseTx.OnTransactionBeforeCommit ]
39+ onCompleted xsync.Set [* baseTx.OnTransactionCompletedFunc ]
3940 }
4041)
4142
@@ -88,6 +89,14 @@ func (tx *Transaction) QueryResultSet(
8889 return nil , xerrors .WithStackTrace (errExecuteOnCompletedTx )
8990 }
9091
92+ if ! options .ExecuteSettings (opts ... ).AllowLazyTx () {
93+ // It needs to execute before create settings because if tx must be not lazy, and it is first query
94+ // change txcontrol during unlazy
95+ if err := tx .UnLazy (ctx ); err != nil {
96+ return nil , err
97+ }
98+ }
99+
91100 settings , err := tx .executeSettings (opts ... )
92101 if err != nil {
93102 return nil , xerrors .WithStackTrace (err )
@@ -100,6 +109,11 @@ func (tx *Transaction) QueryResultSet(
100109 }),
101110 }
102111 if settings .TxControl ().Commit {
112+ err = tx .waitOnBeforeCommit (ctx )
113+ if err != nil {
114+ return nil , err
115+ }
116+
103117 // notification about complete transaction must be sended for any error or for successfully read all result if
104118 // it was execution with commit flag
105119 resultOpts = append (resultOpts ,
@@ -130,6 +144,14 @@ func (tx *Transaction) QueryRow(
130144 onDone (finalErr )
131145 }()
132146
147+ if ! options .ExecuteSettings (opts ... ).AllowLazyTx () {
148+ // It needs to execute before create settings because if tx must be not lazy, and it is first query
149+ // change txcontrol during unlazy
150+ if err := tx .UnLazy (ctx ); err != nil {
151+ return nil , err
152+ }
153+ }
154+
133155 settings := options .ExecuteSettings (
134156 append (
135157 []options.Execute {options .WithTxControl (tx .txControl ())},
@@ -144,6 +166,11 @@ func (tx *Transaction) QueryRow(
144166 }),
145167 }
146168 if settings .TxControl ().Commit {
169+ err := tx .waitOnBeforeCommit (ctx )
170+ if err != nil {
171+ return nil , err
172+ }
173+
147174 // notification about complete transaction must be sended for any error or for successfully read all result if
148175 // it was execution with commit flag
149176 resultOpts = append (resultOpts ,
@@ -192,6 +219,14 @@ func (tx *Transaction) Exec(ctx context.Context, q string, opts ...options.Execu
192219 return xerrors .WithStackTrace (errExecuteOnCompletedTx )
193220 }
194221
222+ if ! options .ExecuteSettings (opts ... ).AllowLazyTx () {
223+ // It needs to execute before create settings because if tx must be not lazy, and it is first query
224+ // change txcontrol during unlazy
225+ if err := tx .UnLazy (ctx ); err != nil {
226+ return err
227+ }
228+ }
229+
195230 settings , err := tx .executeSettings (opts ... )
196231 if err != nil {
197232 return xerrors .WithStackTrace (err )
@@ -204,6 +239,11 @@ func (tx *Transaction) Exec(ctx context.Context, q string, opts ...options.Execu
204239 }),
205240 }
206241 if settings .TxControl ().Commit {
242+ err = tx .waitOnBeforeCommit (ctx )
243+ if err != nil {
244+ return err
245+ }
246+
207247 // notification about complete transaction must be sended for any error or for successfully read all result if
208248 // it was execution with commit flag
209249 resultOpts = append (resultOpts ,
@@ -256,6 +296,14 @@ func (tx *Transaction) Query(ctx context.Context, q string, opts ...options.Exec
256296 return nil , xerrors .WithStackTrace (errExecuteOnCompletedTx )
257297 }
258298
299+ if ! options .ExecuteSettings (opts ... ).AllowLazyTx () {
300+ // It needs to execute before create settings because if tx must be not lazy, and it is first query
301+ // change txcontrol during unlazy
302+ if err := tx .UnLazy (ctx ); err != nil {
303+ return nil , err
304+ }
305+ }
306+
259307 settings , err := tx .executeSettings (opts ... )
260308 if err != nil {
261309 return nil , xerrors .WithStackTrace (err )
@@ -268,6 +316,11 @@ func (tx *Transaction) Query(ctx context.Context, q string, opts ...options.Exec
268316 }),
269317 }
270318 if settings .TxControl ().Commit {
319+ err = tx .waitOnBeforeCommit (ctx )
320+ if err != nil {
321+ return nil , err
322+ }
323+
271324 // notification about complete transaction must be sended for any error or for successfully read all result if
272325 // it was execution with commit flag
273326 resultOpts = append (resultOpts ,
@@ -310,7 +363,12 @@ func (tx *Transaction) CommitTx(ctx context.Context) (finalErr error) {
310363 tx .completed = true
311364 }()
312365
313- err := commitTx (ctx , tx .s .client , tx .s .ID (), tx .ID ())
366+ err := tx .waitOnBeforeCommit (ctx )
367+ if err != nil {
368+ return err
369+ }
370+
371+ err = commitTx (ctx , tx .s .client , tx .s .ID (), tx .ID ())
314372 if err != nil {
315373 if xerrors .IsOperationError (err , Ydb .StatusIds_BAD_SESSION ) {
316374 tx .s .SetStatus (session .StatusClosed )
@@ -360,10 +418,24 @@ func (tx *Transaction) Rollback(ctx context.Context) (finalErr error) {
360418 return nil
361419}
362420
421+ func (tx * Transaction ) OnBeforeCommit (f baseTx.OnTransactionBeforeCommit ) {
422+ tx .onBeforeCommit .Add (& f )
423+ }
424+
363425func (tx * Transaction ) OnCompleted (f baseTx.OnTransactionCompletedFunc ) {
364426 tx .onCompleted .Add (& f )
365427}
366428
429+ func (tx * Transaction ) waitOnBeforeCommit (ctx context.Context ) (resErr error ) {
430+
431+ tx .onBeforeCommit .Range (func (f * baseTx.OnTransactionBeforeCommit ) bool {
432+ resErr = (* f )(ctx )
433+ return resErr == nil
434+ })
435+
436+ return resErr
437+ }
438+
367439func (tx * Transaction ) notifyOnCompleted (err error ) {
368440 tx .completed = true
369441
0 commit comments