Configure statement timeout
Stay organized with collections
Save and categorize content based on your preferences.
This page describes how to set a timeout for a single statement execution using
the Spanner client libraries. This can be used to override the
default timeout configuration of the client library. The statement fails with a
DEADLINE_EXCEEDED
error if the statement cannot finish within the given
timeout value.
These samples show how to set a timeout for a single statement execution in the Cloud Spanner client library.
Go
import(
"context"
"fmt"
"io"
"time"
"cloud.google.com/go/spanner"
"google.golang.org/grpc/codes"
)
funcsetStatementTimeout(wio.Writer,dbstring)error{
client,err:=spanner.NewClient(context.Background(),db)
iferr!=nil{
returnerr
}
deferclient.Close()
_,err=client.ReadWriteTransaction(context.Background(),
func(ctxcontext.Context,txn*spanner.ReadWriteTransaction)error{
// Create a context with a 60-second timeout and apply this timeout to the insert statement.
ctxWithTimeout,cancel:=context.WithTimeout(context.Background(),60*time.Second)
defercancel()
stmt:=spanner.Statement {
SQL:`INSERT Singers (SingerId, FirstName, LastName)
VALUES (39, 'George', 'Washington')`,
}
rowCount,err:=txn.Update(ctxWithTimeout,stmt)
// Get the error code from the error. This function returns codes.OK if err == nil.
code:=spanner.ErrCode (err)
ifcode==codes.DeadlineExceeded{
fmt.Fprintf(w,"Insert statement timed out.\n")
}elseifcode==codes.OK{
fmt.Fprintf(w,"%d record(s) inserted.\n",rowCount)
}else{
fmt.Fprintf(w,"Insert statement failed with error %v\n",err)
}
returnerr
})
iferr!=nil{
returnerr
}
returnnil
}
Java
staticvoidexecuteSqlWithTimeout(){
// TODO(developer): Replace these variables before running the sample.
StringprojectId="my-project";
StringinstanceId="my-instance";
StringdatabaseId="my-database";
try(Spannerspanner=
SpannerOptions.newBuilder().setProjectId(projectId).build().getService()){
DatabaseClientclient=
spanner.getDatabaseClient(DatabaseId.of(projectId,instanceId,databaseId));
executeSqlWithTimeout(client);
}
}
staticvoidexecuteSqlWithTimeout(DatabaseClientclient){
CallContextConfiguratorconfigurator=newCallContextConfigurator(){
public<ReqT,RespT>ApiCallContextconfigure(ApiCallContextcontext,ReqTrequest,
MethodDescriptor<ReqT,RespT>method){
// DML uses the ExecuteSql RPC.
if(method==SpannerGrpc.getExecuteSqlMethod()){
// NOTE: You can use a GrpcCallContext to set a custom timeout for a single RPC
// invocation. This timeout can however ONLY BE SHORTER than the default timeout
// for the RPC. If you set a timeout that is longer than the default timeout, then
// the default timeout will be used.
returnGrpcCallContext.createDefault()
.withCallOptions(CallOptions.DEFAULT.withDeadlineAfter(60L,TimeUnit.SECONDS));
}
// Return null to indicate that the default should be used for other methods.
returnnull;
}
};
// Create a context that uses the custom call configuration.
Contextcontext=
Context.current().withValue(SpannerOptions.CALL_CONTEXT_CONFIGURATOR_KEY,configurator);
// Run the transaction in the custom context.
context.run(()->
client.readWriteTransaction().<long[]>run(transaction->{
Stringsql="INSERT INTO Singers (SingerId, FirstName, LastName)\n"
+"VALUES (20, 'George', 'Washington')";
longrowCount=transaction.executeUpdate(Statement.of(sql));
System.out.printf("%d record inserted.%n",rowCount);
returnnull;
})
);
}
Node.js
/**
* TODO(developer): Uncomment the following lines before running the sample.
*/
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';
// Imports the Google Cloud client library
const{Spanner}=require('@google-cloud/spanner');
// Creates a client
constspanner=newSpanner ({
projectId:projectId,
});
asyncfunctionexecuteSqlWithTimeout(){
// Gets a reference to a Cloud Spanner instance and database.
constinstance=spanner.instance(instanceId);
constdatabase=instance.database(databaseId);
try{
awaitdatabase.runTransactionAsync (asynctx=>{
// NOTE: You can use gaxOptions to set a custom timeout for a single RPC
// invocation. This timeout can however ONLY BE SHORTER than the default timeout
// for the RPC. If you set a timeout that is longer than the default timeout, then
// the default timeout will be used.
constquery={
sql:"INSERT INTO Singers (SingerId, FirstName, LastName) VALUES (110, 'George', 'Washington')",
gaxOptions:{
timeout:60000,// 60 seconds timeout
},
};
constresults=awaittx.run(query);
console.log(`${results[1].rowCountExact} record inserted.`);
awaittx.commit();
});
}catch(err){
console.error('ERROR:',err);
}finally{
awaitdatabase.close();
}
}
executeSqlWithTimeout();
Python
# instance_id = "your-spanner-instance"
# database_id = "your-spanner-db-id"
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)
defwrite(transaction):
# Insert a record and configure the statement timeout to 60 seconds
# This timeout can however ONLY BE SHORTER than the default timeout
# for the RPC. If you set a timeout that is longer than the default timeout,
# then the default timeout will be used.
row_ct = transaction.execute_update(
"INSERT INTO Singers (SingerId, FirstName, LastName) "
" VALUES (110, 'George', 'Washington')",
timeout=60,
)
print("{} record(s) inserted.".format(row_ct))
database.run_in_transaction(write)