Object explorer notifications (#354)

* changing oe protocols to send notifications
This commit is contained in:
Leila Lali
2017-05-23 09:30:11 -07:00
committed by GitHub
parent 6920e6bfd3
commit 63372d327e
10 changed files with 482 additions and 293 deletions

View File

@@ -103,12 +103,130 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
serviceHost.SetRequestHandler(CloseSessionRequest.Type, HandleCloseSessionRequest);
}
public void CloseSession(string uri)
internal async Task HandleCreateSessionRequest(ConnectionDetails connectionDetails, RequestContext<CreateSessionResponse> context)
{
Logger.Write(LogLevel.Verbose, "HandleCreateSessionRequest");
Func<Task<CreateSessionResponse>> doCreateSession = async () =>
{
Validate.IsNotNull(nameof(connectionDetails), connectionDetails);
Validate.IsNotNull(nameof(context), context);
return await Task.Factory.StartNew(() =>
{
string uri = GenerateUri(connectionDetails);
return new CreateSessionResponse { SessionId = uri };
});
};
CreateSessionResponse response = await HandleRequestAsync(doCreateSession, context, "HandleCreateSessionRequest");
if (response != null)
{
RunCreateSessionTask(connectionDetails, response.SessionId);
}
}
internal async Task HandleExpandRequest(ExpandParams expandParams, RequestContext<bool> context)
{
Logger.Write(LogLevel.Verbose, "HandleExpandRequest");
Func<Task<bool>> expandNode = async () =>
{
Validate.IsNotNull(nameof(expandParams), expandParams);
Validate.IsNotNull(nameof(context), context);
string uri = expandParams.SessionId;
ObjectExplorerSession session = null;
NodeInfo[] nodes = null;
ExpandResponse response;
if (!sessionMap.TryGetValue(uri, out session))
{
Logger.Write(LogLevel.Verbose, $"Cannot expand object explorer node. Couldn't find session for uri. {uri} ");
await serviceHost.SendEvent(ExpandCompleteNotification.Type, new ExpandResponse
{
SessionId = expandParams.SessionId,
NodePath = expandParams.NodePath,
ErrorMessage = $"Couldn't find session for session: {uri}"
});
return false;
}
else
{
RunExpandTask(session, expandParams);
return true;
}
};
await HandleRequestAsync(expandNode, context, "HandleExpandRequest");
}
internal async Task HandleRefreshRequest(RefreshParams refreshParams, RequestContext<bool> context)
{
Logger.Write(LogLevel.Verbose, "HandleRefreshRequest");
Validate.IsNotNull(nameof(refreshParams), refreshParams);
Validate.IsNotNull(nameof(context), context);
string uri = refreshParams.SessionId;
ObjectExplorerSession session = null;
ExpandResponse response;
if (!sessionMap.TryGetValue(uri, out session))
{
Logger.Write(LogLevel.Verbose, $"Cannot expand object explorer node. Couldn't find session for uri. {uri} ");
await serviceHost.SendEvent(ExpandCompleteNotification.Type, new ExpandResponse
{
SessionId = refreshParams.SessionId,
NodePath = refreshParams.NodePath,
ErrorMessage = $"Couldn't find session for session: {uri}"
});
}
else
{
RunExpandTask(session, refreshParams, true);
}
await context.SendResult(true);
}
internal async Task HandleCloseSessionRequest(CloseSessionParams closeSessionParams, RequestContext<CloseSessionResponse> context)
{
Logger.Write(LogLevel.Verbose, "HandleCloseSessionRequest");
Func<Task<CloseSessionResponse>> closeSession = () =>
{
Validate.IsNotNull(nameof(closeSessionParams), closeSessionParams);
Validate.IsNotNull(nameof(context), context);
return Task.Factory.StartNew(() =>
{
string uri = closeSessionParams.SessionId;
ObjectExplorerSession session = null;
bool success = false;
if (!sessionMap.TryGetValue(uri, out session))
{
Logger.Write(LogLevel.Verbose, $"Cannot close object explorer session. Couldn't find session for uri. {uri} ");
}
if (session != null)
{
// refresh the nodes for given node path
CloseSession(uri);
success = true;
}
var response = new CloseSessionResponse() { Success = success, SessionId = uri };
return response;
});
};
await HandleRequestAsync(closeSession, context, "HandleCloseSessionRequest");
}
internal void CloseSession(string uri)
{
ObjectExplorerSession session;
if (sessionMap.TryGetValue(uri, out session))
{
// Establish a connection to the specified server/database
// Remove the session from active sessions and disconnect
sessionMap.TryRemove(session.Uri, out session);
connectionService.Disconnect(new DisconnectParams()
{
@@ -116,43 +234,52 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
});
}
}
internal async Task HandleCreateSessionRequest(ConnectionDetails connectionDetails, RequestContext<CreateSessionResponse> context)
private void RunCreateSessionTask(ConnectionDetails connectionDetails, string uri)
{
Logger.Write(LogLevel.Verbose, "HandleCreateSessionRequest");
Func<Task<CreateSessionResponse>> doCreateSession = async () =>
if (connectionDetails != null && !string.IsNullOrEmpty(uri))
{
Validate.IsNotNull(nameof(connectionDetails), connectionDetails);
Validate.IsNotNull(nameof(context), context);
Task task = CreateSessionAsync(connectionDetails, uri);
CreateSessionTask = task;
Task.Run(async () => await task);
}
}
string uri = GenerateUri(connectionDetails);
/// <summary>
/// For tests only
/// </summary>
internal Task CreateSessionTask
{
get;
private set;
}
ObjectExplorerSession session;
if (!sessionMap.TryGetValue(uri, out session))
{
// Establish a connection to the specified server/database
session = await DoCreateSession(connectionDetails, uri);
}
private async Task<SessionCreatedParameters> CreateSessionAsync(ConnectionDetails connectionDetails, string uri)
{
ObjectExplorerSession session;
if (!sessionMap.TryGetValue(uri, out session))
{
// Establish a connection to the specified server/database
session = await DoCreateSession(connectionDetails, uri);
}
CreateSessionResponse response;
if (session == null)
SessionCreatedParameters response;
if (session != null)
{
// Else we have a session available, response with existing session information
response = new SessionCreatedParameters
{
response = new CreateSessionResponse() { Success = false };
}
else
{
// Else we have a session available, response with existing session information
response = new CreateSessionResponse()
{
Success = true,
RootNode = session.Root.ToNodeInfo(),
SessionId = session.Uri
};
}
Success = true,
RootNode = session.Root.ToNodeInfo(),
SessionId = uri,
ErrorMessage = session.ErrorMessage
};
await serviceHost.SendEvent(CreateSessionCompleteNotification.Type, response);
return response;
};
}
return null;
await HandleRequestAsync(doCreateSession, context, "HandleCreateSessionRequest");
}
internal async Task<NodeInfo[]> ExpandNode(ObjectExplorerSession session, string nodePath, bool forceRefresh = false)
@@ -186,9 +313,10 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
connectionDetails.PersistSecurityInfo = true;
ConnectParams connectParams = new ConnectParams() { OwnerUri = uri, Connection = connectionDetails };
ConnectionCompleteParams connectionResult = await Connect(connectParams);
ConnectionCompleteParams connectionResult = await Connect(connectParams, uri);
if (connectionResult == null)
{
// Connection failed and notification is already sent
return null;
}
@@ -198,7 +326,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
}
private async Task<ConnectionCompleteParams> Connect(ConnectParams connectParams)
private async Task<ConnectionCompleteParams> Connect(ConnectParams connectParams, string uri)
{
string connectionErrorMessage = string.Empty;
try
@@ -213,7 +341,11 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
else
{
Logger.Write(LogLevel.Warning, $"Connection Failed for OE. connection error: {connectionErrorMessage}");
await serviceHost.SendEvent(ConnectionCompleteNotification.Type, result);
await serviceHost.SendEvent(CreateSessionCompleteNotification.Type, new SessionCreatedParameters
{
ErrorMessage = result.ErrorMessage,
SessionId = uri
});
return null;
}
@@ -222,108 +354,46 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
{
Logger.Write(LogLevel.Warning, $"Connection Failed for OE. connection error:{connectionErrorMessage} error: {ex.Message}");
// Send a connection failed error message in this case.
ConnectionCompleteParams result = new ConnectionCompleteParams()
SessionCreatedParameters result = new SessionCreatedParameters()
{
Messages = ex.ToString()
ErrorMessage = ex.ToString(),
SessionId = uri
};
await serviceHost.SendEvent(ConnectionCompleteNotification.Type, result);
await serviceHost.SendEvent(CreateSessionCompleteNotification.Type, result);
return null;
}
}
internal async Task HandleExpandRequest(ExpandParams expandParams, RequestContext<ExpandResponse> context)
private void RunExpandTask(ObjectExplorerSession session, ExpandParams expandParams, bool forceRefresh = false)
{
Logger.Write(LogLevel.Verbose, "HandleExpandRequest");
Func<Task<ExpandResponse>> expandNode = async () =>
Task task = ExpandNodeAsync(session, expandParams, forceRefresh);
ExpandTask = task;
Task.Run(async () =>
{
Validate.IsNotNull(nameof(expandParams), expandParams);
Validate.IsNotNull(nameof(context), context);
string uri = expandParams.SessionId;
ObjectExplorerSession session = null;
NodeInfo[] nodes = null;
ExpandResponse response;
if (!sessionMap.TryGetValue(uri, out session))
{
Logger.Write(LogLevel.Verbose, $"Cannot expand object explorer node. Couldn't find session for uri. {uri} ");
}
if (session != null)
{
// expand the nodes for given node path
nodes = await ExpandNode(session, expandParams.NodePath);
}
response = new ExpandResponse() { Nodes = nodes, SessionId = uri };
return response;
};
await HandleRequestAsync(expandNode, context, "HandleExpandRequest");
await task;
});
}
internal async Task HandleRefreshRequest(RefreshParams refreshParams, RequestContext<RefreshResponse> context)
/// <summary>
/// For tests only
/// </summary>
internal Task ExpandTask
{
Logger.Write(LogLevel.Verbose, "HandleRefreshRequest");
Func<Task<RefreshResponse>> refreshNode = async () =>
{
Validate.IsNotNull(nameof(refreshParams), refreshParams);
Validate.IsNotNull(nameof(context), context);
string uri = refreshParams.SessionId;
ObjectExplorerSession session = null;
NodeInfo[] nodes = null;
RefreshResponse response;
if (!sessionMap.TryGetValue(uri, out session))
{
Logger.Write(LogLevel.Verbose, $"Cannot refresh object explorer node. Couldn't find session for uri. {uri} ");
}
if (session != null)
{
// refresh the nodes for given node path
nodes = await ExpandNode(session, refreshParams.NodePath, true);
}
response = new RefreshResponse() { Nodes = nodes, SessionId = uri };
return response;
};
await HandleRequestAsync(refreshNode, context, "HandleRefreshRequest");
get;
set;
}
internal async Task HandleCloseSessionRequest(CloseSessionParams closeSessionParams, RequestContext<CloseSessionResponse> context)
private async Task ExpandNodeAsync(ObjectExplorerSession session, ExpandParams expandParams, bool forceRefresh = false)
{
Validate.IsNotNull(nameof(closeSessionParams), closeSessionParams);
Validate.IsNotNull(nameof(context), context);
Logger.Write(LogLevel.Verbose, "HandleCloseSessionRequest");
Func<Task<CloseSessionResponse>> closeSession = () =>
{
return Task.Factory.StartNew(() =>
{
string uri = closeSessionParams.SessionId;
ObjectExplorerSession session = null;
bool success = false;
if (!sessionMap.TryGetValue(uri, out session))
{
Logger.Write(LogLevel.Verbose, $"Cannot close object explorer session. Couldn't find session for uri. {uri} ");
}
if (session != null)
{
// refresh the nodes for given node path
CloseSession(uri);
success = true;
}
var response = new CloseSessionResponse() {Success = success, SessionId = uri};
return response;
});
};
await HandleRequestAsync(closeSession, context, "HandleCloseSessionRequest");
NodeInfo[] nodes = null;
nodes = await ExpandNode(session, expandParams.NodePath, forceRefresh);
ExpandResponse response = new ExpandResponse() { Nodes = nodes, SessionId = session.Uri, NodePath = expandParams.NodePath };
await serviceHost.SendEvent(ExpandCompleteNotification.Type, response);
}
private async Task HandleRequestAsync<T>(Func<Task<T>> handler, RequestContext<T> requestContext, string requestType)
private async Task<T> HandleRequestAsync<T>(Func<Task<T>> handler, RequestContext<T> requestContext, string requestType)
{
Logger.Write(LogLevel.Verbose, requestType);
@@ -331,11 +401,13 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
{
T result = await handler();
await requestContext.SendResult(result);
return result;
}
catch (Exception ex)
{
await requestContext.SendError(ex.ToString());
}
return default(T);
}
/// <summary>
@@ -441,21 +513,19 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
public string Uri { get; private set; }
public TreeNode Root { get; private set; }
public string ErrorMessage { get; set; }
public static ObjectExplorerSession CreateSession(ConnectionCompleteParams response, IMultiServiceProvider serviceProvider)
{
TreeNode rootNode = new ServerNode(response, serviceProvider);
ServerNode rootNode = new ServerNode(response, serviceProvider);
var session = new ObjectExplorerSession(response.OwnerUri, rootNode, serviceProvider, serviceProvider.GetService<ConnectionService>());
if (!ObjectExplorerUtils.IsSystemDatabaseConnection(response.ConnectionSummary.DatabaseName))
{
// Assuming the databases are in a folder under server node
var children = rootNode.Expand();
var databasesRoot = children.FirstOrDefault(x => x.NodeTypeId == NodeTypes.Databases);
var databasesChildren = databasesRoot.Expand(response.ConnectionSummary.DatabaseName);
var databases = databasesChildren.Where(x => x.NodeType == NodeTypes.Database.ToString());
var databaseNode = databases.FirstOrDefault(d => d.Label == response.ConnectionSummary.DatabaseName);
databaseNode.Label = rootNode.Label;
DatabaseTreeNode databaseNode = new DatabaseTreeNode(rootNode, response.ConnectionSummary.DatabaseName);
session.Root = databaseNode;
}
return session;
}