Should await result of requestcontext.sendresult in case it errors (#520)

- Refactored to use pattern where we wait on the binding queue action to complete, then send the result / error outside of that.
This commit is contained in:
Kevin Cunnane
2017-10-25 12:06:00 -07:00
committed by Karl Burtram
parent 399b03cbd1
commit caf196ea31
6 changed files with 131 additions and 44 deletions

View File

@@ -0,0 +1,28 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System;
namespace Microsoft.SqlTools.ServiceLayer.Scripting
{
public class ScriptingException : Exception
{
public ScriptingException()
: base()
{
}
public ScriptingException(string message, Exception exception)
: base(message, exception)
{
}
public ScriptingException(string message)
: base(message)
{
}
}
}

View File

@@ -23,6 +23,7 @@ using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlTools.ServiceLayer.Utility;
using Microsoft.SqlTools.ServiceLayer.LanguageServices;
namespace Microsoft.SqlTools.ServiceLayer.Scripting
{
@@ -227,55 +228,86 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
/// Runs the async task that performs the scripting operation.
/// </summary>
private void RunSelectTask(ConnectionInfo connInfo, ScriptingParams parameters, RequestContext<ScriptingResult> requestContext)
{
ConnectionServiceInstance.ConnectionQueue.QueueBindingOperation(
key: ConnectionServiceInstance.ConnectionQueue.AddConnectionContext(connInfo, "Scripting"),
bindingTimeout: ScriptingOperationTimeout,
bindOperation: (bindingContext, cancelToken) =>
{
Task.Run(() =>
{
try
{
string script = string.Empty;
ScriptingObject scriptingObject = parameters.ScriptingObjects[0];
try
{
Server server = new Server(bindingContext.ServerConnection);
server.DefaultTextMode = true;
// build object URN
SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder(parameters.ConnectionString);
Urn objectUrn = BuildScriptingObjectUrn(server, connectionStringBuilder, scriptingObject);
string typeName = objectUrn.GetNameForType(scriptingObject.Type);
// select from service broker
if (string.Compare(typeName, "ServiceBroker", StringComparison.CurrentCultureIgnoreCase) == 0)
QueueItem queueItem = ConnectionServiceInstance.ConnectionQueue.QueueBindingOperation(
key: ConnectionServiceInstance.ConnectionQueue.AddConnectionContext(connInfo, "Scripting"),
bindingTimeout: ScriptingOperationTimeout,
bindOperation: (bindingContext, cancelToken) =>
{
script = Scripter.SelectAllValuesFromTransmissionQueue(objectUrn);
}
// select from queues
else if (string.Compare(typeName, "Queues", StringComparison.CurrentCultureIgnoreCase) == 0 ||
string.Compare(typeName, "SystemQueues", StringComparison.CurrentCultureIgnoreCase) == 0)
{
script = Scripter.SelectAllValues(objectUrn);
}
// select from table or view
else
{
Database db = server.Databases[connectionStringBuilder.InitialCatalog];
bool isDw = db.IsSqlDw;
script = new Scripter().SelectFromTableOrView(server, objectUrn, isDw);
}
// send script result to client
requestContext.SendResult(new ScriptingResult { Script = script });
}
catch (Exception e)
return DoScriptSelect(connInfo, parameters, bindingContext);
});
queueItem.ItemProcessed.WaitOne();
var result = queueItem.GetResultAsT<ScriptingResultWithException>();
if (result == null)
{
requestContext.SendError(e);
result = new ScriptingResultWithException()
{
Exception = new ScriptingException(SR.ScriptingUnexpectedError)
};
}
if (result.Exception == null)
{
requestContext.SendResult(result).Wait();
}
else
{
requestContext.SendError(result.Exception);
}
}
catch (Exception e)
{
requestContext.SendError(e);
}
}).ContinueWithOnFaulted(null);
}
return null;
});
private ScriptingResult DoScriptSelect(ConnectionInfo connInfo, ScriptingParams parameters, IBindingContext bindingContext)
{
try
{
string script = string.Empty;
ScriptingObject scriptingObject = parameters.ScriptingObjects[0];
Server server = new Server(bindingContext.ServerConnection);
server.DefaultTextMode = true;
// build object URN
SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder(parameters.ConnectionString);
Urn objectUrn = BuildScriptingObjectUrn(server, connectionStringBuilder, scriptingObject);
string typeName = objectUrn.GetNameForType(scriptingObject.Type);
// select from service broker
if (string.Compare(typeName, "ServiceBroker", StringComparison.CurrentCultureIgnoreCase) == 0)
{
script = Scripter.SelectAllValuesFromTransmissionQueue(objectUrn);
}
// select from queues
else if (string.Compare(typeName, "Queues", StringComparison.CurrentCultureIgnoreCase) == 0 ||
string.Compare(typeName, "SystemQueues", StringComparison.CurrentCultureIgnoreCase) == 0)
{
script = Scripter.SelectAllValues(objectUrn);
}
// select from table or view
else
{
Database db = server.Databases[connectionStringBuilder.InitialCatalog];
bool isDw = db.IsSqlDw;
script = new Scripter().SelectFromTableOrView(server, objectUrn, isDw);
}
// send script result to client
return new ScriptingResult { Script = script };
}
catch (Exception e)
{
return new ScriptingResultWithException() { Exception = e};
}
}
/// <summary>
@@ -317,5 +349,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
}
}
}
internal class ScriptingResultWithException : ScriptingResult
{
public Exception Exception { get; set; }
}
}
}