Skip to content

CSHARP-3552: CSOT: Transactions #1745

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

sanych-sun
Copy link
Member

No description provided.

@sanych-sun sanych-sun requested a review from a team as a code owner August 1, 2025 18:21
@sanych-sun sanych-sun requested review from papafe and removed request for a team August 1, 2025 18:21
@sanych-sun sanych-sun requested review from adelinowona and removed request for papafe August 1, 2025 18:21
Copy link
Contributor

@rstam rstam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

namespace MongoDB.Driver.Core.Bindings
{
// TODO: CSOT: Make it public when CSOT will be ready for GA
internal static class ICoreSessionExtensions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend creating a new ICoreSessionInternal interface to hold the new methods we hope to eventually add to ICoreSession.

These extension methods are useful to make it "look" (to us) like the new methods are already part of ICoreSession.

These extension methods should cast session to ICoreSessionInternal instead of to an open ended set of concrete implementations.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All classes that implement ICoreSession (directly or indirectly) should also now implement ICoreSessionInternal.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Thank you!

{
if (options == null || session.Options.DefaultTransactionOptions?.Timeout == options.Timeout)
{
session.AbortTransaction(cancellationToken);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forwarding the new method to the old method doesn't seem necessary but it also doesn't do any real harm other than adding more lines of code that probably aren't needed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've decided to have this forwarding, just in case there are any external implementation of ICoreSession, this forwarding might reduce risk of breaking client's code.

@@ -182,17 +182,25 @@ public ICoreSession Wrapped

// public methods
/// <inheritdoc />
public virtual void AbortTransaction(CancellationToken cancellationToken = default(CancellationToken))
public virtual void AbortTransaction(CancellationToken cancellationToken = default)
=> AbortTransaction(null, cancellationToken);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have left this method unchanged and forwarded to:

_wrapped.AbortTransaction(cancellationToken);

Let the wrapped class decide whether to forward to the new method or not.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}

/// <inheritdoc />
public virtual Task AbortTransactionAsync(CancellationToken cancellationToken = default(CancellationToken))
public virtual Task AbortTransactionAsync(CancellationToken cancellationToken = default)
=> AbortTransactionAsync(null, cancellationToken);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -223,17 +231,25 @@ public long AdvanceTransactionNumber()
}

/// <inheritdoc />
public virtual void CommitTransaction(CancellationToken cancellationToken = default(CancellationToken))
public virtual void CommitTransaction(CancellationToken cancellationToken = default)
=> CommitTransaction(null, cancellationToken);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


namespace MongoDB.Driver.Core.Misc
{
internal sealed class SystemWatch : IWatch
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this class should be called SystemStopwatch.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

{
public static ReadPreference GetEffectiveReadPreference(this IClientSession session, ReadPreference defaultReadPreference)
// TODO: CSOT: Make it public when CSOT will be ready for GA
internal static class IClientSessionExtensions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend adding an interface called IClientSessionInternal to hold all the internal methods that we plan to eventually move to IClientSession.

These extension methods should be casting session to IClientSessionInternal instead of to an unknown number of concrete implementations. (Yes there is only one implementation now, but that's not the point).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Thank you!

@@ -85,7 +85,11 @@ public CancellationToken CombinedCancellationToken
return _combinedCancellationTokenSource.Token;
}
}
private Stopwatch Stopwatch { get; }
private IWatch Watch { get; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this property should be called Stopwatch.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

public IWatch StartWatch()
{
var startTime = _utcNow;
var mock = new Mock<IWatch>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider renaming mock to mockStopwatch.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -734,8 +699,11 @@ private Mock<IClock> CreateClockMock(DateTime now, bool[] isRetryAttemptsWithTim
}

var mockClock = new Mock<IClock>();
var watchMock = new Mock<IWatch>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider renaming watchMock to mockStopwatch.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same in other places like this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor

@adelinowona adelinowona left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partial review. Will provide next review in a bit

Comment on lines 341 to 345
public Task CommitTransactionAsync(CancellationToken cancellationToken = default)
=> CommitTransactionAsync(null, cancellationToken);

// TODO: CSOT: Make it public when CSOT will be ready for GA
internal async Task CommitTransactionAsync(CommitTransactionOptions options, CancellationToken cancellationToken = default(CancellationToken))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent default parameter syntax for cancellationToken for both methods. Standardize on either default or default(CancellationToken)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

=> CommitTransactionAsync(null, cancellationToken);

// TODO: CSOT: Make it public when CSOT will be ready for GA
internal virtual Task CommitTransactionAsync(CommitTransactionOptions options, CancellationToken cancellationToken = default(CancellationToken))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be cancellationToken = default for consistency

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why doesn't abortTransaction also override its createCommand method?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simply because base class is doing everything what it needs.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we also need to a With() overload that takes the timeout parameter?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might, but not sure if we want to keep this With pattern. We might want to add it for consistency. @BorisDog WDYT?

internal sealed class AbortTransactionOptions
{
public AbortTransactionOptions()
{}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for a new line for this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose we do not need the parameter less constructor at all here. Thank you for bringing attention to this.

internal sealed class CommitTransactionOptions
{
public CommitTransactionOptions()
{}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same no need for a new line?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose we do not need the parameter less constructor at all here. Thank you for bringing attention to this.

Oleksandr Poliakov added 2 commits August 7, 2025 14:43
@sanych-sun sanych-sun requested review from rstam and adelinowona August 7, 2025 22:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants