-
Notifications
You must be signed in to change notification settings - Fork 128
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
chore: add new members in SessionImpl for multiplexed session. Add a … #2961
Changes from 2 commits
d842a58
d1a8427
aaa9585
d062164
e43e071
f458195
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,6 +34,7 @@ | |
import com.google.cloud.Timestamp; | ||
import com.google.cloud.grpc.GrpcTransportOptions; | ||
import com.google.cloud.grpc.GrpcTransportOptions.ExecutorFactory; | ||
import com.google.cloud.spanner.SessionClient.SessionConsumer; | ||
import com.google.cloud.spanner.spi.v1.SpannerRpc; | ||
import com.google.cloud.spanner.v1.stub.SpannerStubSettings; | ||
import com.google.protobuf.ByteString; | ||
|
@@ -60,6 +61,7 @@ | |
import java.util.TimeZone; | ||
import java.util.concurrent.TimeUnit; | ||
import javax.annotation.Nullable; | ||
import org.junit.Assert; | ||
import org.junit.Before; | ||
import org.junit.BeforeClass; | ||
import org.junit.Test; | ||
|
@@ -274,6 +276,49 @@ private static long utcTimeSeconds(int year, int month, int day, int hour, int m | |
return calendar.getTimeInMillis() / 1000; | ||
} | ||
|
||
@Test | ||
public void multiplesSingleUseContext_whenMultiplexedSession_assertValidContext() { | ||
final String dbName = "projects/p1/instances/i1/databases/d1"; | ||
final DatabaseId db = DatabaseId.of(dbName); | ||
final String sessionName = dbName + "/sessions/s1"; | ||
final SpannerImpl spanner = new SpannerImpl(rpc, spannerOptions); | ||
final SessionConsumer consumer = | ||
new SessionConsumer() { | ||
@Override | ||
public void onSessionReady(SessionImpl session) { | ||
ReadContext ctx1 = session.singleUse(TimestampBound.strong()); | ||
session.singleUse(TimestampBound.strong()); | ||
try { | ||
ResultSet resultSet = | ||
ctx1.read("Dummy", KeySet.all(), Collections.singletonList("C")); | ||
assertNotNull(resultSet); | ||
} catch (IllegalStateException ex) { | ||
// in case of multiplexed session we should allow concurrent requests on same session | ||
// and should not receive a IllegalStateException | ||
Assert.fail(); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: do we need this catch block? I think that the test would also fail without it if we get an uncaught IllegalStateException. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm removing test and the current change in |
||
} | ||
|
||
@Override | ||
public void onSessionCreateFailure(Throwable t, int createFailureForSessionCount) {} | ||
}; | ||
Session sessionProto = | ||
Session.newBuilder() | ||
.setCreateTime(getCurrentGoogleTimestamp()) | ||
.setName(sessionName) | ||
.setMultiplexed(true) | ||
.build(); | ||
Mockito.when( | ||
rpc.createSession( | ||
Mockito.eq(dbName), | ||
Mockito.anyString(), | ||
Mockito.anyMap(), | ||
optionsCaptor.capture(), | ||
Mockito.eq(true))) | ||
.thenReturn(sessionProto); | ||
spanner.getSessionClient(db).createMultiplexedSession(consumer); | ||
} | ||
|
||
@Test | ||
public void newSingleUseContextClosesOldSingleUseContext() { | ||
ReadContext ctx = session.singleUse(TimestampBound.strong()); | ||
|
@@ -515,4 +560,11 @@ public void multiUseReadOnlyTransactionReturnsMissingTransactionId() throws Pars | |
() -> txn.readRow("Dummy", Key.of(), Collections.singletonList("C"))); | ||
assertEquals(ErrorCode.INTERNAL, e.getErrorCode()); | ||
} | ||
|
||
private com.google.protobuf.Timestamp getCurrentGoogleTimestamp() { | ||
arpan14 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
long current = System.currentTimeMillis(); | ||
long seconds = TimeUnit.MILLISECONDS.toSeconds(current); | ||
int nanos = (int) TimeUnit.MILLISECONDS.toNanos(current - TimeUnit.SECONDS.toMillis(seconds)); | ||
return com.google.protobuf.Timestamp.newBuilder().setSeconds(seconds).setNanos(nanos).build(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This works here now, but I'm not sure this is the actual thing that needs to be changed to allow multiple operations on the same session. The
isValid
flag is set to false wheninvalidate()
is called. That is called fromSessionImpl#setActive(SessionTransaction)
method. That again sets theactiveTransaction
on aSessionImpl
. That field is what I think needs to be refactored for multiplexed sessions, asSessionImpl#activeTransaction
is not really a thing anymore, as oneSessionImpl
can now have multiple transactions. At least; the latter is what I get from the fact that we just create a normalSessionImpl
instance when we create a multiplexed sessions.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, there are a few more changes that should be done to generalize
SessionTransaction
interface. I'll need to still do the changes. Will put that in a separate PR.