//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using Microsoft.SqlServer.Dac.Projects;
using Microsoft.SqlTools.Hosting.Protocol;
using Microsoft.SqlTools.ServiceLayer.Hosting;
using Microsoft.SqlTools.ServiceLayer.SqlProjects.Contracts;
using Microsoft.SqlTools.ServiceLayer.Utility;
namespace Microsoft.SqlTools.ServiceLayer.SqlProjects
{
///
/// Main class for SqlProjects service
///
class SqlProjectsService
{
private static readonly Lazy instance = new Lazy(() => new SqlProjectsService());
///
/// Gets the singleton instance object
///
public static SqlProjectsService Instance => instance.Value;
private Lazy> projects = new Lazy>(() => new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase));
///
/// that maps Project URI to Project
///
public ConcurrentDictionary Projects => projects.Value;
///
/// Initializes the service instance
///
///
public void InitializeService(ServiceHost serviceHost)
{
// Project-level functions
serviceHost.SetRequestHandler(OpenSqlProjectRequest.Type, HandleOpenSqlProjectRequest, isParallelProcessingSupported: true);
serviceHost.SetRequestHandler(CloseSqlProjectRequest.Type, HandleCloseSqlProjectRequest, isParallelProcessingSupported: true);
serviceHost.SetRequestHandler(NewSqlProjectRequest.Type, HandleNewSqlProjectRequest, isParallelProcessingSupported: true);
// SQL object script calls
serviceHost.SetRequestHandler(AddSqlObjectScriptRequest.Type, HandleAddSqlObjectScriptRequest, isParallelProcessingSupported: false);
serviceHost.SetRequestHandler(DeleteSqlObjectScriptRequest.Type, HandleDeleteSqlObjectScriptRequest, isParallelProcessingSupported: false);
serviceHost.SetRequestHandler(ExcludeSqlObjectScriptRequest.Type, HandleExcludeSqlObjectScriptRequest, isParallelProcessingSupported: false);
}
#region Handlers
#region Project-level functions
internal async Task HandleOpenSqlProjectRequest(SqlProjectParams requestParams, RequestContext requestContext)
{
await RunWithErrorHandling(() => GetProject(requestParams.ProjectUri), requestContext);
}
internal async Task HandleCloseSqlProjectRequest(SqlProjectParams requestParams, RequestContext requestContext)
{
await RunWithErrorHandling(() => Projects.TryRemove(requestParams.ProjectUri, out _), requestContext);
}
internal async Task HandleNewSqlProjectRequest(NewSqlProjectParams requestParams, RequestContext requestContext)
{
await RunWithErrorHandling(async () =>
{
await SqlProject.CreateProjectAsync(requestParams.ProjectUri, requestParams.SqlProjectType, requestParams.DatabaseSchemaProvider);
GetProject(requestParams.ProjectUri); // load into the cache
}, requestContext);
}
#endregion
#region Sql object script calls
internal async Task HandleAddSqlObjectScriptRequest(SqlProjectScriptParams requestParams, RequestContext requestContext)
{
await RunWithErrorHandling(() => GetProject(requestParams.ProjectUri).SqlObjectScripts.Add(new SqlObjectScript(requestParams.Path)), requestContext);
}
internal async Task HandleDeleteSqlObjectScriptRequest(SqlProjectScriptParams requestParams, RequestContext requestContext)
{
await RunWithErrorHandling(() => GetProject(requestParams.ProjectUri).SqlObjectScripts.Delete(requestParams.Path), requestContext);
}
internal async Task HandleExcludeSqlObjectScriptRequest(SqlProjectScriptParams requestParams, RequestContext requestContext)
{
await RunWithErrorHandling(() => GetProject(requestParams.ProjectUri).SqlObjectScripts.Exclude(requestParams.Path), requestContext);
}
#endregion
#endregion
#region Helper methods
private async Task RunWithErrorHandling(Action action, RequestContext requestContext)
{
await RunWithErrorHandling(async () => await Task.Run(action), requestContext);
}
private async Task RunWithErrorHandling(Func action, RequestContext requestContext)
{
try
{
await action();
await requestContext.SendResult(new ResultStatus()
{
Success = true,
ErrorMessage = null
});
}
catch (Exception ex)
{
await requestContext.SendResult(new ResultStatus()
{
Success = false,
ErrorMessage = ex.Message
});
}
}
private SqlProject GetProject(string projectUri)
{
if (!Projects.ContainsKey(projectUri))
{
Projects[projectUri] = new SqlProject(projectUri);
}
return Projects[projectUri];
}
#endregion
}
}